poj 1679 The Unique MST (次小生成树算法)
The Unique MST
| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 16309 | Accepted: 5652 |
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 following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
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 following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Input
The
first line contains a single integer t (1 <= t <= 20), the number
of test cases. Each case represents a graph. It begins with a line
containing two integers n and m (1 <= n <= 100), the number of
nodes and edges. Each of the following m lines contains a triple (xi,
yi, wi), indicating that xi and yi are connected by an edge with weight =
wi. For any two nodes, there is at most one edge connecting them.
Output
For each input, if the MST is unique, print the total cost of it, or otherwise print the string 'Not Unique!'.
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!
Source
View Code
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; const int INF = 0x7ffffff; const int MAXN = 105; const int MAXM = 10005; int n,m; //n是点的数目,m是边得数目 int mst,secmst; //mst是最小生成树的大小,secmst是次小生成树的大小 struct node{ int v,u,w; int select; //标记是否在在最小生成树中 }edge[MAXM]; struct node1{ //一个等价类的邻接表 int to; int next; }links[MAXN]; int head[MAXN]; //头节点位置 int end[MAXN]; //尾节点位置,便于两条邻接表的合并 int length[MAXN][MAXN]; //每两点在最小生成树上路径中最长边长 int p[MAXN]; //并查集部分 int find(int x){ if(x == p[x]) return x; p[x] = find(p[x]); return p[x]; } bool cmp(node a, node b){ if (a.w != b.w)return a.w<b.w; if (a.u != b.u)return a.u<b.u; return a.v<b.v; } void kruskal(){ memset(head, -1, sizeof(head)); int i,j,k,u; int x,y; for (i=1; i<=n; i++){ //初始化邻接表,对于每个节点添加一条指向其自身的边,表示以i为 p[i] = i; //代表的集合只有点i; links[i].to = i; links[i].next = head[i]; head[i] = i; end[i] = i; } sort(edge, edge+m, cmp); k = 0; for (i=0; i<m; i++){ if (k == n-1) break; x = find(edge[i].u); y = find(edge[i].v); if (x != y){ //遍历两个节点所在的集合 for (j=head[x]; j!=-1; j=links[j].next) for (u=head[y]; u!=-1; u=links[u].next) length[links[j].to][links[u].to] = length[links[u].to][links[j].to] = edge[i].w; //每次合并两个等价类的时候,分别属于两个等价类的两点间的最长边一定是当前加入的边 links[end[y]].next = head[x]; //合并两个邻接表 end[y] = end[x]; p[x] = y; k++; edge[i].select = 1; mst += edge[i].w; } } } int main(){ // freopen("in.txt", "r", stdin); int i; int T; int u,v,w; scanf("%d",&T); while (T--){ mst = 0; scanf("%d%d",&n,&m); for (i=0; i<m; i++){ scanf("%d %d %d",&u,&v,&w); edge[i].u = u; edge[i].v = v; edge[i].w = w; edge[i].select = 0; } kruskal(); secmst = INF; for (i=0; i<m; i++){ if (!edge[i].select) secmst = min(secmst, mst+edge[i].w-length[edge[i].u][edge[i].v]); } if (secmst != mst) printf("%d\n",mst); else printf("Not Unique!\n"); } return 0; }
posted on 2013-03-22 17:50 shijianupc 阅读(189) 评论(0) 收藏 举报

浙公网安备 33010602011771号