标签:from color main ems hid was pen ace top
InputThe input begins with a line containing an integer T(T<=50), the number of test cases. For each case, the first line begins with three integers ---- the above mentioned n (4<=n<=50), m (0<=m<=1000) and k (1<=k<=5, 2k<=n). Then m lines follow, each containing three integers u,v and w, indicating that there is a broken road connecting house u an d v, and the cost to repair that road is w(1<=w<=1000).OutputFor each test case, if you cannot find a proper way to repair the roads, output a string "No solution" in a line. Otherwise, output the minimum cost to repair the roads in a line.Sample Input
2 4 3 1 4 2 10 3 1 9 2 3 10 6 7 2 1 5 1000 2 6 1000 1 3 1 2 3 1 3 4 1 4 5 1 4 6 1
Sample Output
29 5
斯坦纳树
求包含前k个点和后k个点的最小生成子树。
用状态压缩来表示某个点是否被包含进了子树,然后跑一大堆SPFA。
按照题目的要求,前k个点和后k个点只要一对在一棵子树中即可,不需要所有2*k个点在同一棵子树中,所以最后要在森林中DP。
并不明白SPFA的初始状态为什么要那么写,注释掉的代码wa掉了。先抄题解为敬2333
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 const int INF=0x3f3f3f3f; 10 const int mxn=2100; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 14 while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 15 return x*f; 16 } 17 struct edge{ 18 int v,nxt,dis; 19 }e[mxn]; 20 int hd[mxn],mct=0; 21 void add_edge(int u,int v,int d){ 22 e[++mct].v=v;e[mct].nxt=hd[u];e[mct].dis=d;hd[u]=mct;return; 23 } 24 int n,m,k; 25 int id[60]; 26 int dis[mxn][60]; 27 bool vis[mxn][60]; 28 bool inq[mxn][60]; 29 void init(){ 30 memset(hd,0,sizeof hd); 31 memset(vis,0,sizeof vis); 32 memset(dis,0x3f,sizeof dis); 33 memset(id,0,sizeof id); 34 mct=0; 35 return; 36 } 37 queue<pair<int,int> >q; 38 void SPFA(){ 39 while(!q.empty()){ 40 int w=q.front().first; 41 int u=q.front().second; 42 q.pop(); 43 vis[w][u]=0; 44 for(int i=hd[u];i;i=e[i].nxt){ 45 int v=e[i].v; 46 if(dis[w|id[v]][v]>dis[w][u]+e[i].dis){ 47 dis[w|id[v]][v]=dis[w][u]+e[i].dis; 48 if(!vis[v][w]){ 49 q.push(make_pair(w|id[v],v)); 50 vis[w|id[v]][v]=1; 51 } 52 } 53 } 54 } 55 return; 56 } 57 bool ok(int w){ 58 int res=0; 59 for(int i=1;w;i++){ 60 if(w&1){ 61 if(i>k)res++;//保持出入数量相等 62 else res--; 63 } 64 w>>=1; 65 } 66 if(res)return 0;return 1; 67 } 68 int dp[mxn]; 69 void DP(){ 70 int i,j;int ed=1<<(2*k); 71 memset(dp,0x3f,sizeof dp); 72 for(i=0;i<ed;i++) 73 for(j=1;j<=n;j++) 74 dp[i]=min(dp[i],dis[i][j]); 75 for(i=1;i<ed;i++){ 76 if(ok(i)){ 77 for(j=(i-1)&i;j;j=(j-1)&i){ 78 if(ok(j)){ 79 dp[i]=min(dp[i],dp[j]+dp[i-j]);//合并状态 80 } 81 } 82 } 83 } 84 return; 85 } 86 int main(){ 87 int i,j; 88 int T=read(); 89 while(T--){ 90 init(); 91 n=read();m=read();k=read(); 92 int u,v,d; 93 for(i=1;i<=m;i++){ 94 u=read();v=read();d=read(); 95 add_edge(u,v,d); 96 add_edge(v,u,d); 97 } 98 for(i=1;i<=k;i++){ 99 id[i]=1<<(i-1); 100 id[n-i+1]=1<<(k+i-1); 101 dis[id[i]][i]=0; 102 dis[id[n-i+1]][n-i+1]=0; 103 } 104 int ed=1<<(2*k); 105 for(int s=0;s<ed;s++){ 106 for(int i=1;i<=n;i++){ 107 for(int p=(s-1)&s;p;p=(p-1)&s) 108 dis[s][i]=min(dis[s][i],dis[p|id[i]][i]+dis[(s-p)|id[i]][i]); 109 if(dis[s][i]<INF && !vis[s][i]) 110 q.push(make_pair(s,i));vis[s][i]=1; 111 } 112 SPFA(); 113 } 114 /* for(i=1;i<=n;i++){ 115 if(id[i]){ 116 vis[id[i]][i]=1; 117 q.push(make_pair(id[i],i)); 118 } 119 } 120 SPFA();*/ 121 DP(); 122 if(dp[ed-1]>=INF)printf("No solution\n"); 123 else printf("%d\n",dp[ed-1]); 124 } 125 return 0; 126 }
标签:from color main ems hid was pen ace top
原文地址:http://www.cnblogs.com/SilverNebula/p/6329623.html