标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 24201 | Accepted: 8596 |
Description
Input
Output
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!
题意:判断是否存在唯一的最小生成树。
思路:先求出一个最小生成树。在这颗树上先加入(x,y),加入后一定会成环,如果删除(x,y)以外最大的一条边,会得到加入(x,y)时权值最小的一棵树。如果加入的边和删除的边相等,则最小生成不是唯一的。
收获:了解了次小生成树。
#include <cstdio> #include <iostream> #include <cstdlib> #include <algorithm> #include <ctime> #include <cmath> #include <string> #include <cstring> #include <stack> #include <queue> #include <list> #include <vector> #include <map> #include <set> using namespace std; const int INF=0x3f3f3f3f; const double eps=1e-10; const double PI=acos(-1.0); #define maxn 500 int n, m; int a[maxn][maxn]; int used[maxn][maxn]; int mmax[maxn][maxn]; int vis[maxn]; int dis[maxn]; int pre[maxn]; int prim() { int ans = 0; memset(vis, 0, sizeof vis); memset(used, 0, sizeof used); memset(mmax, 0 ,sizeof mmax); for(int i = 2; i <= n; i++) { dis[i] = a[1][i]; pre[i] = 1; } vis[1] = 1; dis[1] = 0; for(int i = 1; i < n; i++) { int temp = INF; int k = -1; for(int j = 1; j <= n; j++) { if(!vis[j] && temp > dis[j]) { temp = dis[j]; k = j; } } if(k == -1) return ans; ans += temp; vis[k] = 1; used[k][pre[k]] = used[pre[k]][k] = 1; mmax[pre[k]][k] = temp; for(int j = 1; j <= n; j++) mmax[j][k] = max(mmax[j][pre[k]],mmax[pre[k]][k] );//找最大的边权的边。 for(int j = 1; j <= n; j++) { if(!vis[j] && dis[j] > a[k][j]) { dis[j] = a[k][j]; pre[j] = k; } } } return ans; } int main() { int t; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); int u, v, w; memset(a, INF, sizeof a); for(int i = 0; i < m; i++) { scanf("%d%d%d", &u, &v, &w); a[u][v] = a[v][u] = w; } int mst = prim(); int flag = 0; for(int i = 1; i <= n; i++) for(int j = i+1; j <= n; j++) { if(a[i][j] == INF || used[i][j] == 1) continue; if(a[i][j] == mmax[i][j])//判断加入的边和删除的边是否相等。 { flag = 1; break; } } if(flag) printf("Not Unique!\n"); else printf("%d\n",mst); } return 0; }
标签:
原文地址:http://www.cnblogs.com/ZP-Better/p/4734298.html