标签:har 接下来 连通 insert algorithm stdin using mem 一点
小铭铭最近进入了某情报部门,该部门正在被如何建立安全的通道连接困扰。
第一行包含三个整数 n;m;p,表示情报站的数量,可以建立的通道数量和重要情报站的数量。
接下来 m 行,每行包含三个整数 ui;vi;wi,表示可以建立的通道。最后有 p 行,每行包含两个整数 ci;di,表示重要情报站的频道和情报站的编号。
输出一行一个整数,表示任意相同频道的情报站之间都建立通道连接所花费的最少资源总量。
选择 (1; 5); (3; 5); (2; 5); (4; 5) 这 4 对情报站连接。
正解:斯坦纳森林。
斯坦纳树加强版——斯坦纳森林。
首先,我们直接把所有关键点状压起来,整个跑一遍斯坦纳树。
然后对于每个状态,我们忽略它的根是什么,直接取每层状态的最小值。
然后我们就可以直接枚举子集合并了,仔细想想发现这样做是对的。
但是我们要注意一点,两个不同根的状态合并,合并以后可能是不连通的,所以我们要判断状态的合法性。
如果一个状态既不是不包含一个频道,又不是全部包含一个频道,那么这个状态是不合法的,可以直接丢掉。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define all (1<<p) 16 #define N (1010) 17 #define il inline 18 #define RG register 19 #define ll long long 20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 21 22 using namespace std; 23 24 struct edge{ int nt,to,dis; }g[10010]; 25 26 int f[N][1<<11],ff[1<<11],head[N],vis[N],q[1000010],mt[N],cal[12],id[12][12],n,m,p,num; 27 28 il int gi(){ 29 RG int x=0,q=1; RG char ch=getchar(); 30 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 31 if (ch==‘-‘) q=-1,ch=getchar(); 32 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 33 return q*x; 34 } 35 36 il void insert(RG int from,RG int to,RG int dis){ 37 g[++num]=(edge){head[from],to,dis},head[from]=num; return; 38 } 39 40 il int check(RG int s){ 41 for (RG int i=1;i<=10;++i) 42 if ((s&cal[i]) && (s&cal[i])!=cal[i]) return 0; 43 return 1; 44 } 45 46 il void spfa(RG int s){ 47 RG int h=0,t=0; 48 for (RG int i=1;i<=n;++i) 49 if (f[i][s]!=f[0][0]) q[++t]=i,vis[i]=1; 50 while (h<t){ 51 RG int x=q[++h],v; 52 for (RG int i=head[x];i;i=g[i].nt){ 53 v=g[i].to; 54 if (f[v][s]>f[x][s]+g[i].dis){ 55 f[v][s]=f[x][s]+g[i].dis; 56 if (!vis[v]) vis[v]=1,q[++t]=v; 57 } 58 } 59 vis[x]=0; 60 } 61 return; 62 } 63 64 il void work(){ 65 n=gi(),m=gi(),p=gi(); 66 for (RG int i=1,u,v,w;i<=m;++i) 67 u=gi(),v=gi(),w=gi(),insert(u,v,w),insert(v,u,w); 68 memset(f,0x3f3f3f,sizeof(f)),memset(ff,0x3f3f3f,sizeof(ff)); 69 for (RG int i=1,x,y;i<=p;++i){ 70 x=gi(),y=gi(),id[x][++id[x][0]]=y; 71 mt[y]=1<<(i-1),f[y][mt[y]]=0; 72 } 73 for (RG int s=1;s<all;++s){ 74 for (RG int i=1;i<=n;++i){ 75 for (RG int sub=(s-1)&s;sub;sub=(sub-1)&s) 76 f[i][s]=min(f[i][s],f[i][sub]+f[i][s^sub]); 77 ff[s]=min(ff[s],f[i][s]); 78 } 79 spfa(s); 80 } 81 for (RG int i=1;i<=10;++i) 82 for (RG int j=1;j<=id[i][0];++j) cal[i]|=mt[id[i][j]]; 83 for (RG int s=1;s<all;++s){ 84 if (!check(s)) continue; 85 for (RG int sub=(s-1)&s;sub;sub=(sub-1)&s){ 86 if (!check(sub)) continue; 87 ff[s]=min(ff[s],ff[sub]+ff[s^sub]); 88 } 89 } 90 printf("%d\n",ff[all-1]); return; 91 } 92 93 int main(){ 94 File("pipe"); 95 work(); 96 return 0; 97 }
标签:har 接下来 连通 insert algorithm stdin using mem 一点
原文地址:http://www.cnblogs.com/wfj2048/p/6918407.html