【POJ 1679 The Unique MST】最小生成树

无向连通图(无重边),判断最小生成树是否唯一,若唯一求边权和。

分析生成树的生成过程,只有一个圈内出现权值相同的边才会出现权值和相等但“异构”的生成树。(并不一定是最小生成树)

分析贪心策略求最小生成树的过程(贪心地选最短的边来扩充已加入生成树的顶点集合U),发现只有当出现“U中两个不同的点到V-U中同一点的距离同时为当前最短边”时,才会出现“异构”的最小生成树。

上图为kruscal和prim生成过程中可能遇到的相等边的情况,红色和蓝色的为权值相等的边。

可以看到kruscal由于事先将所有边按权值排序,所以在构造MST的过程中,当发现权值相同的边时,需要遍历之前遇到过的所有相同权值的边来判断是否发生“争抢同一点”的情况,若发现即可判定存在“异构”最小生成树。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int MAX_N=105;
 6 const int MAX_M=5005;
 7
 8 int par[MAX_N];
 9 void init()
10 {
11     memset(par,-1,sizeof(par));
12 }
13 int find(int x)
14 {
15     if(par[x]==-1) return x;
16     return par[x]=find(par[x]);
17 }
18 void unite(int x,int y)
19 {
20     x=find(x);
21     y=find(y);
22     if(x!=y) par[x]=y;
23 }
24 bool same(int x,int y)
25 {
26     return find(x)==find(y);
27 }
28
29 int t;
30 int n,m;
31 struct Edge
32 {
33     int u,v,w;
34 }e[MAX_M];
35
36 bool cmp(Edge e1,Edge e2)
37 {
38     return e1.w<e2.w;
39 }
40
41 bool inter(Edge e1,Edge e2)
42 {
43     if(e1.u==e2.u||e1.u==e2.v||e1.v==e2.u||e1.v==e2.v) return true;
44     else return false;
45 }
46
47 int kruscal()
48 {
49     int ans=0;
50     init();
51     ans+=e[0].w;
52     unite(e[0].u,e[0].v);
53     int cur_w=e[0].w;
54     for(int i=1;i<m;i++)
55     {
56         if(same(e[i].u,e[i].v))
57         {
58             for(int j=i-1;e[j].w==e[i].w;j--)
59             {
60                 if(inter(e[i],e[j]))//判两条边有无交点
61                 {
62                     ans=-1;
63                     break;
64                 }
65             }
66         }else
67         {
68             unite(e[i].u,e[i].v);
69             ans+=e[i].w;
70             cur_w=e[i].w;
71         }
72     }
73     return ans;
74 }
75
76 int main()
77 {
78     freopen("1679.txt","r",stdin);
79     scanf("%d",&t);
80     while(t--)
81     {
82         scanf("%d%d",&n,&m);
83         for(int i=0;i<m;i++)
84         {
85             scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
86         }
87         if(n==1) {printf("0\n"); continue;}
88         sort(e,e+m,cmp);
89         int ans=kruscal();
90         if(ans==-1)
91             printf("Not Unique!\n");
92         else printf("%d\n",ans);
93     }
94     return 0;
95 }

kruscal

而prim由于每次都选连结U和V-U的边,所以不会遇到kruscal那样蓝色的可能误判的边(我开始就WA在这里),因此只需在加入一个新点更新其他点的mincost时判断有没有和mincost值相等的另一条边的即可。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <vector>
 4 #include <queue>
 5 using namespace std;
 6 const int MAX_N=105;
 7 const int MAX_M=5005;
 8 const int INF=100000;
 9 typedef pair<int,int> P;//cost,to
10 struct Edge
11 {
12     int to,cost;
13     Edge(){}
14     Edge(int tt,int cc):to(tt),cost(cc){}
15 };
16 int t;
17 int n,m;
18 vector<Edge> G[MAX_N];
19 int vis[MAX_N];
20 int mincost[MAX_N];
21
22 int prim()
23 {
24     int ans=0;
25     int flag=0;
26     priority_queue<P> que;
27     memset(vis,0,sizeof(vis));
28     for(int i=1;i<=n;i++) mincost[i]=INF;
29     que.push(P(0,1));
30     mincost[1]=0;
31     while(!que.empty())
32     {
33         P p=que.top();
34         que.pop();
35         int v=p.second;
36         if(vis[v]||mincost[v]<p.first) continue;
37         vis[v]=1;
38         mincost[v]=p.first;
39         ans+=mincost[v];
40         for(int i=0;i<G[v].size();i++)
41         {
42             int u=G[v][i].to;
43             if(!vis[u])
44             {
45                 if(mincost[u]>G[v][i].cost&&G[v][i].cost<INF)
46                 {
47                     mincost[u]=G[v][i].cost;
48                     que.push(P(mincost[u],u));
49                 }else if(mincost[u]==G[v][i].cost)//存在到达点u权值相等且都为最小值的边
50                 {
51                     flag=1;
52                     break;
53                 }
54             }
55         }
56         if(flag) break;
57     }
58     if(flag) ans=-1;
59     return ans;
60 }
61 int main()
62 {
63     freopen("1679.txt","r",stdin);
64     scanf("%d",&t);
65     while(t--)
66     {
67         scanf("%d%d",&n,&m);
68         for(int i=1;i<=n;i++) G[i].clear();
69         for(int i=0;i<m;i++)
70         {
71             int u,v,w;
72             scanf("%d%d%d",&u,&v,&w);
73             G[u].push_back(Edge(v,w));
74             G[v].push_back(Edge(u,w));
75         }
76         if(n==1) {printf("0\n"); continue;}
77         int ans=prim();
78         if(ans==-1)
79             printf("Not Unique!\n");
80         else printf("%d\n",ans);
81     }
82     return 0;
83 }

prim_priorityqueue

时间: 2024-12-27 16:29:10

【POJ 1679 The Unique MST】最小生成树的相关文章

poj 1679 The Unique MST 最小生成树

点击打开链接 http://poj.org/problem?id=1679 题意:给一个无向图,问最小生成树是否唯一,如果唯一就输出最小生成树的所有边的权值的和,如果不唯一,那么就输出Not Unique! 思路:在用prime算法求最小生成树的过程中,在找到权值最小的一个节点之后,先判断一下,这个节点的权值是否可以由好几条路径求得,并且权值都等于当前权值,如果是的话,那么最小生成树就不唯一.那么如何判断呢?可以用一个flag数组标记,0代表这个点得到当前权值的路径唯一,1代表不唯一,初始化全为

poj 1679 The Unique MST (判断最小生成树是否唯一)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20679   Accepted: 7255 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

POJ 1679 The Unique MST(求最小生成树是否唯一)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20430   Accepted: 7186 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

POJ - 1679 The Unique MST (次小生成树)

Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the followin

poj 1679 The Unique MST (次小生成树)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20293   Accepted: 7124 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire

poj 1679 The Unique MST 【次小生成树】【模板】

题目:poj 1679 The Unique MST 题意:给你一颗树,让你求最小生成树和次小生成树值是否相等. 分析:这个题目关键在于求解次小生成树. 方法是,依次枚举不在最小生成树上的边,然后添加到最小生成树上,然后把原树上添加了之后形成环的最长的边删去,知道一个最小的.就是次小生成树. 这些需要的都可以在求解最小生成树的时候处理出来. AC代码: #include <cstdio> #include <cstring> #include <iostream> #i

poj 1679 The Unique MST (判定最小生成树是否唯一)

题目链接:http://poj.org/problem?id=1679 The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 29408   Accepted: 10520 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spannin

poj 1679 The Unique MST (判断最小生成树是否唯一)

链接:poj 1679 题意:判断最小生成树是否唯一, 若唯一,输出最小权值和,否则,输出  Not Unique! 判断最小生成树是否唯一的思路: 1.对图中的每一条边,扫描其他边,如果存在相同权值的边,则对该边做标记 2.然后用Kruskal算法或Prim算法求MST 3.求得MST后,如果该MST中未包含做了标记的边,即可判断MST唯一: 如果包含做了标记的边,则依次去掉这些边的一条边,再求MST, 如果求得的MST权值和原来的MST的权值一样,即可判断MST不唯一. 个人思路是先求最小生

POJ 1679 The Unique MST (Kruskal 判最小生成树是否唯一)

The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 21646 Accepted: 7661 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected

POJ 1679 The Unique MST 推断最小生成树是否唯一

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22715   Accepted: 8055 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undire