zoukankan      html  css  js  c++  java
  • 「牛客」十二桥问题

    题目链接

    戳我

    (ps:)如果没报名可能看不了,有权限,不宜公布题面(可以去baidu)

    (Solution)

    怎么全部写的是分层图或者状压啊?没人跟我一样写折半吗?

    我们发现(k)只有(12),很小啊,那应该从(k)下手

    我们发现有用的点最多(25)个,我们将这点(x)离散记为(id[x]),他到(y)最短路径为(dis[id[x]][y])

    我们可以搜索这(k)条边的顺序+方向.但是这样复杂度很显然不对

    观察他是从(1)开始在回到(1),这相当了两个从(1)开始的路径,我们只需要处理一个,再把他们拼起来就好了。

    于是我们搜索(k/2)的顺序+方向。记录下(F[S][k]()状态为(S),即选了那些边,以节点(k)结尾的最小长度())的答案。这个应该很好弄吧.只要每次加上两点之间的最短路即可,如果不明白可以看代码

    于是我们答案就可以算了.

    我们枚举一种状态(X),然后另一种状态就是枚举状态的补集,令它为(Y).

    然后在枚举(i和j)表示第一种状态以(i)结尾,第二种以(j)结尾.则答案就是(F[X][i]+F[Y][j]+dis[id[i]][j];)

    注意(k)为单数的情况有点特殊,(k/2+1)的答案也要算一算

    搞不懂为什么考场上没有想到状压.

    可能要卡卡常但是有点懒,懒得卡了。本来考试可以过的,开了(O2),但是比赛结束后就没开了????

    #pragma GCC optimize("O2")
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-fwhole-program")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-fstrict-overflow")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-skip-blocks")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("-funsafe-loop-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #include<bits/stdc++.h>
    #define int long long
    #define rg register
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    const int inf=1e17;
    int read(){
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    struct node{
        int to,next,v;
    }a[4000100];
    struct node1{
        int id,v;
        bool operator < (const node1 &a) const{
            return a.v<v;
        }
    }p,now;
    priority_queue<node1>q;
    int head[100010],cnt,dis[100010],f[100010],n,m,k,x,y,z;
    int X[100010],Y[100010],Z[100010],vis[100010],tot,bj[100010];
    int Dis[26][100010];
    void add(int x,int y,int c){
        a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,head[x]=cnt;
    }
    int calc(int x){
        int cnt=0;
        while(x)
            cnt+=x&1,x>>=1;
        return cnt;
    }
    void dij(int s){
        p.id=s,p.v=0,q.push(p);
        memset(dis,127/3,sizeof(dis));
        memset(f,0,sizeof(f));
        dis[s]=0;
        while(!q.empty()){
            now=q.top(),q.pop();
            if(f[now.id]) continue;
            f[now.id]=1;
            for(int i=head[now.id];i;i=a[i].next){
                int v=a[i].to;
                if(dis[v]>dis[now.id]+a[i].v)
                    dis[v]=dis[now.id]+a[i].v,p.id=v,p.v=dis[v],q.push(p);
            }
        }
    }
    int flag[1001],c[1001],d[1001];
    int Ans[100001][30];
    int Ans2[100001][30];
    void dfs(int x,int ans){
        if(x==k/2){
            int ANS=0,last=1;
            for(int i=1;i<=x;i++){
                if(!d[i]) swap(X[c[i]],Y[c[i]]);
                ANS+=Dis[vis[last]][X[c[i]]]+Z[c[i]],last=Y[c[i]];
                if(i==x) Ans[ans][vis[Y[c[i]]]]=min(Ans[ans][vis[Y[c[i]]]],ANS);
                if(!d[i]) swap(X[c[i]],Y[c[i]]);
            }
        }
        if(x==k-k/2){
            int ANS=0,last=1;
            if(k%2==0) {
                if(!d[x]) swap(X[c[x]],Y[c[x]]);
                Ans2[ans][vis[Y[c[x]]]]=Ans[ans][vis[Y[c[x]]]];
                if(!d[x]) swap(X[c[x]],Y[c[x]]);
                return ;
            }
            for(int i=1;i<=x;i++){
                if(!d[i]) swap(X[c[i]],Y[c[i]]);
                ANS+=Dis[vis[last]][X[c[i]]]+Z[c[i]],last=Y[c[i]];
                if(i==x) Ans2[ans][vis[Y[c[i]]]]=min(Ans2[ans][vis[Y[c[i]]]],ANS);
                if(!d[i]) swap(X[c[i]],Y[c[i]]);
            }
            return ;
        }
        for(int i=1;i<=k;i++)
            if(!flag[i])
                for(int j=0;j<=1;j++)
                    d[x+1]=j,c[x+1]=i,flag[i]=1,dfs(x+1,ans|(1<<(i-1))),flag[i]=0;
    }
    int minx=inf,len;
    void dfs(int x,int ans,int l){
        if(ans==k/2){
            int now=l^len;
            for(int j=1;j<=tot;j++)
                for(int k=1;k<=tot;k++)
                    minx=min(minx,Ans2[now][j]+Ans[l][k]+Dis[k][bj[j]]);
            return ;
        }
        for(int i=x+1;i<=k;i++)
            dfs(i,ans+1,l|(1<<(i-1)));
    }
    main(){
        n=read(),m=read(),k=read();
        tot=1,bj[tot]=1,vis[1]=1;
        for(int i=1;i<=m;i++){
            x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
            if(i<=k){
                X[i]=x,Y[i]=y,Z[i]=z;
                if(!vis[x]) vis[x]=++tot,bj[tot]=x;
                if(!vis[y]) vis[y]=++tot,bj[tot]=y;
            }
        }
        memset(Ans,127/3,sizeof(Ans));
        memset(Ans2,127/3,sizeof(Ans2));
        for(int s=1;s<=tot;s++){
            dij(bj[s]);
            for(int i=1;i<=n;i++)
                Dis[s][i]=dis[i];
        }
        dfs(0,0);
        len=(1<<k)-1,Ans2[0][1]=0,Ans[0][1]=0;
        dfs(0,0,0);
        cout<<minx;
    }
    
  • 相关阅读:
    Python 基于Python实现的ssh兼sftp客户端(上)
    lintcode: 最长连续序列
    lintcode:颜色分类
    lintcode: 堆化
    lintcode: 旋转图像
    lintcode: 寻找旋转排序数组中的最小值
    lintcode: 跳跃游戏 II
    lintcode:最小差
    华为:数独填充
    华为:字符集合
  • 原文地址:https://www.cnblogs.com/hbxblog/p/11821449.html
Copyright © 2011-2022 走看看