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

Posted stranger-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了次小生成树 克鲁斯卡尔修改相关的知识,希望对你有一定的参考价值。

    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("
");
 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
",MST);
65     else
66         printf("Not Unique!
");
67 }
68 int main()
69 {
70     int T;
71     scanf("%d
",&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 }

 

 



以上是关于次小生成树 克鲁斯卡尔修改的主要内容,如果未能解决你的问题,请参考以下文章

prim算法(最小生成树)

次小生成树

P4180 模板严格次小生成树[BJWC2010](严格次小生成树)

次小生成树

次小生成树

poj1679次小生成树入门题