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

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 }  
View Code

 

posted @ 2019-08-16 01:21  zjxxcn  阅读(186)  评论(0编辑  收藏  举报