BZOJ 3590: [Snoi2013]Quare

首先有一个性质,一个双联通图一定可以拆成一个小的双联通子图和一条链

一个点可以视为权值为0的双联通图或者一个点的链

状压DP,枚举子集

O(3^n*n^2)

#include<cstdio>
#include<algorithm>
#define rep(i,x,y) for (int i=x; i<y; i++)
using namespace std;
int cnt,M[1005][1005],H[5005][15][15],last[15],G[5005][15][2],F[5005];
struct node{
	int to,next,val;
}e[1000005];
void add(int a,int b,int c){
	e[++cnt].to=b;
	e[cnt].next=last[a];
	e[cnt].val=c;
	last[a]=cnt;
}
int main(){
	int T;
	scanf("%d",&T);
	while (T--){
		int n,m;
		scanf("%d%d",&n,&m);
		cnt=0;
		for (int i=0; i<n; i++) last[i]=0;
		rep(i,0,n) rep(j,0,n) M[i][j]=1e9;
		for (int i=1; i<=m; i++){
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			x--,y--;
			add(x,y,z);
			add(y,x,z);
			M[x][y]=min(M[x][y],z);
			M[y][x]=min(M[y][x],z);
		}
		int Max=(1<<n);

		rep(i,0,Max) rep(x,0,n) rep(y,0,n) H[i][x][y]=1e9;

		for (int i=0; i<n; i++) H[1<<i][i][i]=0;

		for (int i=0; i<Max; i++)
			for (int S=0; S<n; S++)
				for (int T=0; T<n; T++)
					if (H[i][S][T]!=1e9){
						for (int To=0; To<n; To++){
							if (i&(1<<To)) continue;
							H[i|(1<<To)][S][To]=min(H[i|(1<<To)][S][To],H[i][S][T]+M[To][T]);
						}
					}

		rep(i,0,Max) rep(S,0,n) G[i][S][0]=G[i][S][1]=1e9;
		for (int i=0; i<Max; i++)
			for (int S=0; S<n; S++)
				for (int j=last[S]; j; j=e[j].next){
					int T=e[j].to;
					if (i&(1<<T)){
						if (G[i][S][0]>=e[j].val){
							G[i][S][1]=G[i][S][0];
							G[i][S][0]=e[j].val;
						}
						else if (G[i][S][1]>e[j].val) G[i][S][1]=e[j].val;
					}
				}
		
		rep(i,0,Max) F[i]=1e9;
		
		for (int i=0; i<n; i++) F[1<<i]=0;
		for (int i=0; i<Max; i++)
			for (int pre=(i-1)&i; pre; pre=(pre-1)&i){
				int now=i-pre;
				for (int S=0; S<n; S++)
					for (int T=0; T<n; T++){
						if (now&(1<<S) && now&(1<<T)){
							int Sum=H[now][S][T]+G[pre][S][0];
							if (Sum>=1e9) continue;
							if (S!=T) Sum+=G[pre][T][0];
							else Sum+=G[pre][T][1];
							F[i]=min(F[i],F[pre]+Sum);
						}
					}
			}
		if (F[Max-1]==1e9) printf("impossible
");
		else printf("%d
",F[Max-1]);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/silenty/p/9858240.html