bzoj 5180: [Baltic2016]Cities
Description
给定n个点,m条双向边的图。其中有k个点是重要的。每条边都有一定的长度。
现在要你选定一些边来构成一个图,要使得k个重要的点相互连通,求边的长度和的最小值。
Input
共m+2行
第1行:n,k,m,n个点,k个重要的点,m条边;
第2行共K个点
第3至第m+2行,每行包括3个数字,a,b,c,表示有一条从a到b长度为c的双向路径
k<=5
n<=10^5
1<=m<=2*(10^5)
Output
共1行,即最小长度和
Sample Input
4 3 6
1 3 4
1 2 4
1 3 9
1 4 6
2 3 2
2 4 5
3 4 8
1 3 4
1 2 4
1 3 9
1 4 6
2 3 2
2 4 5
3 4 8
Sample Output
11
斯坦纳树,这题卡spfa,我了个去。。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 int const N=1e5+10; 5 int const M=100; 6 ll const inf=1e15; 7 struct edge{ 8 int to,nt,w; 9 }e[N<<2]; 10 struct node{ 11 ll d; 12 int x; 13 node(ll _d,int _x) { 14 d=_d; x=_x; 15 } 16 bool operator < ( const node &rhs) const{ 17 return d>rhs.d; 18 } 19 }; 20 int cnt,h[N],n,p,m,vis[N],a[10],id[N]; 21 ll f[N][M],d[N]; 22 queue<node> q; 23 inline int read(){ 24 int x=0; char c=0; 25 while (!isdigit(c)) c=getchar(); 26 while (isdigit(c)) x=x*10+(c^48),c=getchar(); 27 return x; 28 } 29 void add(int a,int b,int c){ 30 e[++cnt].to=b; 31 e[cnt].w=c; 32 e[cnt].nt=h[a]; 33 h[a]=cnt; 34 } 35 void dijkstra(){ 36 memset(vis,0,sizeof(vis)); 37 while (!q.empty()){ 38 int x; 39 while (!q.empty()){ 40 x=q.front().x; 41 q.pop(); 42 if(!vis[x]) break; 43 } 44 vis[x]=1; 45 for(int i=h[x];i;i=e[i].nt){ 46 int v=e[i].to; 47 if(d[v]>d[x]+e[i].w){ 48 d[v]=d[x]+e[i].w; 49 q.push(node(d[v],v)); 50 } 51 } 52 } 53 } 54 int main(){ 55 // scanf("%d%d%d",&n,&p,&m); 56 n=read(); 57 p=read(); 58 m=read(); 59 for(int i=1;i<=p;i++) { 60 a[i]=read(); 61 id[a[i]]=i; 62 } 63 while (m--){ 64 int x,y,z; 65 x=read(); y=read(); z=read() ; 66 // scanf("%d%d%d",&x,&y,&z); 67 add(x,y,z); 68 add(y,x,z); 69 } 70 for(int i=1;i<=n;i++) 71 for(int j=0;j<(1<<p);j++) 72 f[i][j]=inf; 73 for(int i=1;i<=p;i++) 74 f[a[i]][1<<id[a[i]]-1]=0; 75 for(int k=1;k<(1<<p);k++){ 76 for(int i=1;i<=n;i++) d[i]=inf; 77 for(int i=1;i<=n;i++){ 78 for(int x=k&(k-1); x;x=(x-1)&k){ 79 ll tmp=f[i][x]+f[i][k-x]; 80 f[i][k]=min(f[i][k],tmp); 81 } 82 if(f[i][k]<inf){ 83 q.push(node(f[i][k],i)); 84 d[i]=f[i][k]; 85 } 86 } 87 dijkstra(); 88 for(int i=1;i<=n;i++) f[i][k]=d[i]; 89 } 90 printf("%lld\n",f[a[1]][(1<<p)-1]); 91 return 0; 92 }