Codeforces Round #529 (Div. 3) F.Make It Connected
题意:
有 n 个顶点,每个顶点有个花费 a[ i ],连接顶点 u,v 需要花费 a[v]+a[u]的代价。
有 m 个特殊边,每条边有三个参数 u,v,w 代表的意思是连接 u,v 的花费可以不是 a[v]+a[u] 而是 w(当然选择小的那个啦)。
求联通所有的顶点需要的最少花费?
题解:
首先,需要建图,改如何建呢?
考虑到贪心的思路,首先不考虑 m 个特殊边,如何用最少的花费联通所有顶点呢?
答案是找到 a[ i ] 最少的顶点 i,其他 n-1 个顶点全部连向 i 。
将这 n-1 条边记录下来,在加上 m 条特殊边,然后,就是求最小生成树的模板题了,emmmmmm
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 using namespace std; 6 #define ll __int64 7 #define pb(x) push_back(x) 8 const int maxn=2e5+10; 9 10 int n,m; 11 ll a[maxn]; 12 struct Node 13 { 14 int u,v; 15 ll w; 16 Node(int a,int b,ll c):u(a),v(b),w(c){} 17 }; 18 vector<Node >G; 19 void addEdge(int u,int v,ll w) 20 { 21 G.pb(Node(u,v,w)); 22 } 23 24 int fa[2*maxn]; 25 int Find(int x) 26 { 27 int r=x; 28 while(r != fa[r]) 29 r=fa[r]; 30 while(fa[x] != r) 31 { 32 int temp=fa[x]; 33 fa[x]=r; 34 x=temp; 35 } 36 return r; 37 } 38 bool Union(int x,int y) 39 { 40 x=Find(x),y=Find(y); 41 if(x != y) 42 { 43 fa[x]=y; 44 return true; 45 } 46 return false; 47 } 48 bool cmp(Node _a,Node _b) 49 { 50 return _a.w < _b.w; 51 } 52 ll Solve() 53 { 54 sort(G.begin(),G.end(),cmp); 55 ll res=0; 56 for(int i=0;i < G.size();++i) 57 { 58 Node e=G[i]; 59 if(Union(e.u,e.v)) 60 res += e.w; 61 } 62 return res; 63 } 64 int main() 65 { 66 scanf("%d%d",&n,&m); 67 int minP=0; 68 for(int i=1;i <= n;++i) 69 { 70 fa[i]=i; 71 scanf("%I64d",a+i); 72 minP=(minP == 0 || a[minP] > a[i] ? i:minP); 73 } 74 for(int i=1;i <= n;++i) 75 addEdge(i,minP,a[i]+a[minP]); 76 for(int i=1;i <= m;++i) 77 { 78 int u,v; 79 ll w; 80 scanf("%d%d%I64d",&u,&v,&w); 81 addEdge(u,v,w); 82 } 83 printf("%I64d",Solve()); 84 return 0; 85 }