BZOJ3590 SNOI2013Quare(状压dp)
可能作为最优解的边双都可以这样生成:初始时边双内只有一个点,每次选取边双内部两点(可以相同)和一个当前不在边双内的点集,以该两点为起止点找一条链(当然如果两点相同就是个环)将点集串起来,加入边双。状压dp模拟这个过程即可。注意找链时对二元环特判。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 12 #define M 42 #define inf 100000000 #define rep(i,t,S) for (int t=S,i=lg2[t&-t];t;t^=t&-t,i=lg2[t&-t]) char getc (){ char c= getchar (); while ((c< 'A' ||c> 'Z' )&&(c< 'a' ||c> 'z' )&&(c< '0' ||c> '9' )) c= getchar (); return c;} int gcd( int n, int m){ return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1; char c= getchar (); while (c< '0' ||c> '9' ) { if (c== '-' ) f=-1;c= getchar ();} while (c>= '0' &&c<= '9' ) x=(x<<1)+(x<<3)+(c^48),c= getchar (); return x*f; } int n,m,a[N][N],f[1<<N],g[N][N][1<<N],lg2[1<<N]; struct data{ int x,y,z; }edge[M]; int main() { #ifndef ONLINE_JUDGE freopen ( "bzoj3590.in" , "r" ,stdin); freopen ( "bzoj3590.out" , "w" ,stdout); const char LL[]= "%I64d\n" ; #else const char LL[]= "%lld\n" ; #endif int T=read(); while (T--) { n=read(),m=read(); for ( int i=1;i<=m;i++) edge[i].x=read()-1,edge[i].y=read()-1,edge[i].z=read(); memset (f,42, sizeof (f)); for ( int i=0;i<n;i++) f[1<<i]=0,lg2[1<<i]=i; memset (g,42, sizeof (g)); for ( int i=0;i<n;i++) for ( int j=0;j<n;j++) for ( int k=1;k<=m;k++) if (edge[k].x==i&&edge[k].y==j||edge[k].x==j&&edge[k].y==i) g[i][j][0]=min(g[i][j][0],edge[k].z); for ( int i=1;i<(1<<n);i++) { rep(x,p,(1<<n)-1^i) rep(y,q,(1<<n)-1^i) if (x!=y||i!=(i&-i)) rep(j,o,i) g[x][y][i]=min(g[x][y][i],g[j][y][i^(1<<j)]+g[j][x][0]); else { int mn=inf,mn2=inf; for ( int j=1;j<=m;j++) if (edge[j].x==x&&edge[j].y==lg2[i]||edge[j].x==lg2[i]&&edge[j].y==x) if (edge[j].z<mn) mn2=mn,mn=edge[j].z; else if (edge[j].z<mn2) mn2=edge[j].z; g[x][y][i]=mn+mn2; } } for ( int i=1;i<(1<<n);i++) for ( int j=i-1&i;j;j=j-1&i) rep(x,u,i^j) rep(y,v,i^j) { f[i]=min(f[i],f[i^j]+g[x][y][j]); if (x==y) break ; } if (f[(1<<n)-1]<inf) printf ( "%d\n" ,f[(1<<n)-1]); else printf ( "impossible\n" ); } return 0; } |
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步