标签:oid logs end ring cto 保留 amp ++ problem
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=3371
思路:
这道题很明显是一道最小生成树的题目,有点意思的是,它事先已经让几个点联通了。正是因为它先联通了几个点,所以为了判断连通性 很容易想到用并查集+kruskal。
不过要注意 这题有一个坑点,就是边数很多 上限是25000,排序的话可能就超时了。而点数则比较少 上限是500,所以很多人选择用Prim做。但我个人觉得这样连通性不好判断。其实边数多没关系,我们主要去重就好啦,用邻接矩阵存下两点间的最小权重 再排序即可,这样就不会超时啦~
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 const int inf=1e5; 7 struct node{ 8 int v,u,w; 9 bool operator <(const node &x) const{ 10 return w<x.w; 11 } 12 }; 13 int pre[505]; 14 int mp[505][505]; 15 int n,m,k; 16 int cnt; 17 vector<node>v; 18 void init(){ 19 for(int i=1;i<=n;i++){ 20 pre[i]=i; 21 for (int j=1; j<=n; j++) { 22 mp[i][j]=inf; 23 } 24 } 25 } 26 int query(int x){ 27 int r=x; 28 while (pre[x]!=x) { 29 x=pre[x]; 30 } 31 pre[r]=x; 32 return x; 33 } 34 bool join(int x,int y){ 35 int fx=query(x); 36 int fy=query(y); 37 if(fx!=fy){ 38 pre[fx]=fy; 39 return true; 40 } 41 return false; 42 } 43 int kruskal(){ 44 int res=0; 45 for(int i=0;i<v.size();i++){ 46 if(join(v[i].v, v[i].u)){ 47 res+=v[i].w; 48 } 49 } 50 return res; 51 } 52 int main(){ 53 int t; 54 int res; 55 scanf("%d",&t); 56 while (t--) { 57 cnt=0; 58 v.clear(); 59 scanf("%d%d%d",&n,&m,&k); 60 init(); 61 for (int i=0; i<m; i++) { 62 int v,u,w; 63 scanf("%d%d%d",&v,&u,&w); 64 mp[v][u]=min(mp[v][u],w);//保留最小权重 65 } 66 for (int i=0; i<k; i++) { 67 int num,a,b; 68 scanf("%d",&num); 69 if(num) scanf("%d",&a); 70 for (int j=1; j<num; j++) { 71 scanf("%d",&b); 72 join(a, b); 73 } 74 } 75 for (int i=1; i<=n; i++) { 76 for (int j=1; j<=n; j++) { 77 if(mp[i][j]==inf || i==j) continue; 78 v.push_back({i,j,mp[i][j]});//重新导入边,去掉了重复部分 79 } 80 } 81 sort(v.begin(), v.end()); 82 res=kruskal(); 83 for (int i=1; i<=n; i++) { 84 if(pre[i]==i) cnt++;//算连通块个数 85 } 86 if(cnt==1) printf("%d\n",res); 87 else printf("-1\n"); 88 } 89 }
HDU 3371 Connect the Cities(并查集+Kruskal)
标签:oid logs end ring cto 保留 amp ++ problem
原文地址:http://www.cnblogs.com/uniles/p/7287076.html