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

    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 }

 

 
posted @ 2018-09-20 22:20  灬从此以后灬  阅读(140)  评论(0编辑  收藏  举报