「牛客」十二橋問題

題目連接

戳我node

\(ps:\)若是沒報名可能看不了,有權限,不宜公佈題面(能夠去baidu)c++

\(Solution\)

怎麼所有寫的是分層圖或者狀壓啊?沒人跟我同樣寫折半嗎?oop

咱們發現\(k\)只有\(12\),很小啊,那應該從\(k\)下手spa

咱們發現有用的點最多\(25\)個,咱們將這點\(x\)離散記爲\(id[x]\),他到\(y\)最短路徑爲\(dis[id[x]][y]\)code

咱們能夠搜索這\(k\)條邊的順序+方向.可是這樣複雜度很顯然不對ip

觀察他是從\(1\)開始在回到\(1\),這至關了兩個從\(1\)開始的路徑,咱們只須要處理一個,再把他們拼起來就行了。get

因而咱們搜索\(k/2\)的順序+方向。記錄下\(F[S][k](\)狀態爲\(S\),即選了那些邊,以節點\(k\)結尾的最小長度\()\)的答案。這個應該很好弄吧.只要每次加上兩點之間的最短路便可,若是不明白能夠看代碼it

因而咱們答案就能夠算了.io

咱們枚舉一種狀態\(X\),而後另外一種狀態就是枚舉狀態的補集,令它爲\(Y\).ast

而後在枚舉\(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;
}
相關文章
相關標籤/搜索