码迷,mamicode.com
首页 > 其他好文 > 详细

次小生成树 克鲁斯卡尔修改

时间:2018-09-20 22:59:52      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:return   eof   最大值   ace   mst   namespace   克鲁斯   pre   lan   

    http://bailian.openjudge.cn/practice/1679?lang=en_US

题意 判断最小生成树是否唯一 如果唯一输出大小 不唯一输出Not Unique!
O(n*n+mlogm)
AC代码
 1 #include <bits/stdc++.h>
 2 #define pb push_back
 3 #define mp make_pair
 4 #define fi first
 5 #define se second
 6 #define all(a) (a).begin(), (a).end()
 7 #define fillchar(a, x) memset(a, x, sizeof(a))
 8 #define huan printf("\n");
 9 #define debug(a,b) cout<<a<<" "<<b<<" "<<endl;
10 using namespace std;
11 const int maxn=1e3+10,inf=0x3f3f3f3f;
12 typedef long long ll;
13 int n,m;
14 struct edge
15 {
16     int u,v,w;
17     bool vis;
18 }e[maxn*10];
19 vector<int>G[maxn];
20 int per[maxn],maxdis[maxn][maxn];
21 bool cmp(edge a,edge b)
22 {
23     return a.w < b.w;
24 }
25 int _find(int x)
26 {
27     return x == per[x] ? x: per[x] = _find(per[x]);
28 }
29 void kruskal()
30 {
31     sort(e,e+m,cmp);
32     for(int i=0; i<=n; i++)//初始化
33     {
34         G[i].clear();
35         G[i].push_back(i);
36         per[i]=i;
37     }
38     int MST=0,jishu=0;//MST是最小生成树的值
39     for(int i=0; i<m; i++)
40     {
41         if(jishu==n-1)  break;//小优化
42         int x1=_find(e[i].u),x2=_find(e[i].v);
43         if(x1!=x2)
44         {
45             jishu++;
46             e[i].vis=true;//这条边已经用过了
47             MST+=e[i].w;
48             per[x1]=x2;
49             for(int j=0; j<G[x1].size(); j++)//更新两点之间距离的最大值,每次合并两个等价类时分别属于两个等价类的两个点之间的最长边一定是当前加入的边
50                 for(int k=0; k<G[x2].size(); k++)
51                     maxdis[G[x1][j]][G[x2][k]]=maxdis[G[x2][k]][G[x1][j]]=e[i].w;//因为后面的边会越来越大,所以这里可以直接等于当前边的长度
52             vector<int> temp=G[x2];        //现在已经属于一棵树了,那么我们就将点添加到相应的集合中
53             for(int j=0; j<G[x1].size(); j++)
54                 G[x2].push_back(G[x1][j]);
55             for(int j=0; j<temp.size(); j++)
56                 G[x1].push_back(temp[j]);
57         }
58     }
59     int SecondST=inf;//次小生成树的权值
60     for(int i=0; i<m; i++)
61         if(!e[i].vis)
62             SecondST=min(SecondST,MST+e[i].w-maxdis[e[i].u][e[i].v]);
63     if(SecondST>MST)
64         printf("%d\n",MST);
65     else
66         printf("Not Unique!\n");
67 }
68 int main()
69 {
70     int T;
71     scanf("%d\n",&T);
72     while(T--)
73     {
74         scanf("%d%d",&n,&m);
75         for(int i=0; i<m; i++)
76         {
77             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
78             e[i].vis = false;
79         }
80         kruskal();
81     }
82     return 0;
83 }

 

 

次小生成树 克鲁斯卡尔修改

标签:return   eof   最大值   ace   mst   namespace   克鲁斯   pre   lan   

原文地址:https://www.cnblogs.com/stranger-/p/9683709.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!