戳我node
\(ps:\)若是沒報名可能看不了,有權限,不宜公佈題面(能夠去baidu)c++
怎麼所有寫的是分層圖或者狀壓啊?沒人跟我同樣寫折半嗎?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; }