bzoj3590: [Snoi2013]Quare

传送门

impossible打错结果WA了半个小时我觉得自己也是挺强的……
顺便发现我模拟赛的时候从来没有打对过任何一道dp……
果然dp就是智商的分水岭啊QAQ
首先最优解肯定是若干个环套在一起,或者说一个强连通分量加上一条链可以组成一个更大的强联通分量。
我们分别记录一下状态,(h1[u][S])表示点(u)(S)的点集中的随便哪个点的最小距离,(h2[u][S])表示次小距离
(g[u][v][S])表示一条链,其中链的两端为(u,v),链上的点为(S)的最小花费
(f[S])表示(S)中的点组成强联通分量时的最小花费
然后用强联通分量组成更大的强联通分量即可
代码抄袭CQzhangyu的

//minamoto
#include<bits/stdc++.h>
#define rint register int
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
const int N=105,M=(1<<12)+5;
int n,m,lim,T,u,v,vva,w,tot;
struct eg{int v,nx,w;}e[N];int head[N],val[N],Log[M],h1[15][M],h2[15][M],g[15][15][M],f[M];
inline void add(int u,int v,int w){e[++tot]={v,head[u],w},head[u]=tot;}
void solve(){
	scanf("%d%d",&n,&m),lim=(1<<n)-1;
	memset(head,0,sizeof(head)),tot=0;
	fp(i,0,m-1)scanf("%d%d%d",&u,&v,&w),add(u-1,v-1,w),add(v-1,u-1,w);
	fp(i,0,n-1)Log[1<<i]=i;
	memset(h1,0x0f,sizeof(h1)),memset(h2,0x0f,sizeof(h2)),memset(g,0x0f,sizeof(g)),memset(f,0x0f,sizeof(f));
	fp(S,0,lim)for(rint ta=lim^S;ta;ta-=ta&-ta){
		u=Log[ta&-ta];go(u)if(S&(1<<v)){
			if(e[i].w<h1[u][S])h2[u][S]=h1[u][S],h1[u][S]=e[i].w;
			else cmin(h2[u][S],e[i].w);
		}
	}
	fp(i,0,n-1)g[i][i][1<<i]=f[1<<i]=0;
	fp(S,1,lim)for(rint ta=S;ta;ta-=ta&-ta)for(rint tb=S;tb;tb-=tb&-tb){
		u=Log[ta&-ta],vva=Log[tb&-tb];if(u==vva)continue;
		go(vva)if(S&(1<<v))cmin(g[u][vva][S],g[u][v][S^(1<<vva)]+e[i].w);
	}
	fp(S,1,lim){
		if(S==(S&-S))continue;
		for(rint T=(S-1)&S;T;T=(T-1)&S)for(rint ta=T;ta;ta-=ta&-ta)for(rint tb=T;tb;tb-=tb&-tb){
			u=Log[ta&-ta],vva=Log[tb&-tb];
			if(u==vva)cmin(f[S],f[S^T]+g[u][vva][T]+h1[u][S^T]+h2[u][S^T]);
			else cmin(f[S],f[S^T]+g[u][vva][T]+h1[u][S^T]+h1[vva][S^T]);
		}
	}
	if(f[lim]==0x0f0f0f0f)puts("impossible");
	else printf("%d
",f[lim]);
}
int main(){
//	freopen("testdata.in","r",stdin);
	scanf("%d",&T);
	while(T--)solve();
	return 0;
}
原文地址:https://www.cnblogs.com/bztMinamoto/p/10017800.html