题解:
一道比较水的题
但这个测试数据极弱我也不知道我的代码正确性是不是有保证
构成一个边双联通
可以由两个有一个公共点的边双联通或者一个边双加一条链构成
所以我们需要要预处理出所有环
令f[i][j][k]表示起点为i,终点为j,经过点的状态为k,这样递推
那么最后环就是加上j-i这条边就可以了
但是注意一个二元环,一个为最长边一个为次长边
其他环都不会用到次长边
代码:
#include <bits/stdc++.h> using namespace std; #define IL inline #define rint register int #define dep(i,t,h) for (rint i=t;i>=h;i--) #define rep(i,h,t) for (rint i=h;i<=t;i++) char ss[1<<24],*A=ss,*B=ss; IL char gc() { return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T>void read(T &x) { rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48); while(c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } void umin(int &x,int y) { if (x>y) x=y; } int dp[15][15][1<<14],ff[1<<14],f[20][20][2],n,m; bool tf[1<<14]; const int INF=1e9; int main() { int T; read(T); rep(tt,1,T) { read(n); read(m); rep(i,1,n) rep(j,1,n) f[i][j][0]=f[i][j][1]=INF; rep(i,1,m) { int x,y,z; read(x); read(y); read(z); if (z<=f[x][y][0]) f[x][y][1]=f[x][y][0],f[x][y][0]=z, f[y][x][1]=f[y][x][0],f[y][x][0]=z; else if (z<f[x][y][1]) f[x][y][1]=z,f[y][x][1]=z; } rep(i,1,n) rep(j,1,n) rep(k,1,(1<<n)-1) dp[i][j][k]=INF; rep(i,1,n) dp[i][i][(1<<(i-1))]=0; rep(i,1,(1<<n)-1) { int a[100]; int cnt=0; rep(j,1,n) if ((i>>(j-1))&1) a[++cnt]=j; rep(i1,1,cnt) rep(j1,1,cnt) rep(k,1,n) if (!((i>>(k-1))&1)) umin(dp[a[i1]][k][i|(1<<(k-1))],dp[a[i1]][a[j1]][i]+f[a[j1]][k][0]); } rep(i,1,(1<<n)-1) tf[i]=0; rep(i,1,(1<<n)-1) ff[i]=INF; rep(i,1,n) rep(j,1,n) if (i!=j) tf[(1<<(i-1))+(1<<(j-1))]=1, ff[(1<<(i-1))+(1<<(j-1))]=min(INF,f[i][j][0]+f[i][j][1]); rep(i,1,(1<<n)-1) if (!tf[i]) rep(j,1,n) rep(k,1,n) umin(ff[i],dp[j][k][i]+f[j][k][0]); rep(i,1,(1<<n)-1) for (int j=i;j;j=i&(j-1)) rep(k,1,n) if (j&(1<<(k-1))) umin(ff[i],ff[(i^j)|(1<<(k-1))]+ff[j]); if (ff[(1<<n)-1]!=INF) cout<<ff[(1<<n)-1]<<endl; else cout<<"impossible"<<endl; } return 0; }