Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 25369 | Accepted: 9055 |
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!
次小生成树的两种方法:
1:用求最小生成树的方法,求出最小生成树,并记录下该最小生成树上的所有边!
对该生成树上的所有边都进行枚举。对边集中,除了生成树上某条边的集合,构造最小生成树,并记录下最小值!
当生成树上的边枚举完,得到的值的大小就是次小生成树的大小!
2: 首先求出原图最小生成树,权值之和为min 枚举添加每条不在最小生成树上的边 ,加上以后一定会形成一个环。 找到环上除了(u,v)以外的权值最大的边,把它删掉,计算当前生成树的权值之和。 枚举完所有边之后,得到的最小值即为次小生成树的权值。 具体实现时,更简单的方法是从每个节点i遍历整个最小生成树 定义F[i][j]为在生成树上,从i到j的路径上最大的边的权值。通过BFS,求出F[i][j]的值 然后对于添加每条不在最小生成树中的边(i,j),并删去该环中的原生成树的的最大边。 新的生成树权值之和就是Min + w(i,j) – F[i][j] 记录其最小值,则为次小生成树。
AC:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn = 500; const int inf = 0x7ffff; int n,m,cost[maxn][maxn],low[maxn],belong[maxn]; bool vis[maxn],used[maxn][maxn]; int Prim() { int k = 1,MIN,ans = 0; memset(vis,false,sizeof(vis)); memset(used,false,sizeof(used)); vis[k] = true; for(int i = 1; i <= n; i++) { low[i] = cost[k][i]; belong[i] = k; } for(int i = 1; i < n; i++) { MIN = inf; for(int j = 1; j <= n; j++) { if(vis[j] == false && low[j] < MIN) { MIN = low[j]; k = j; } } vis[k] = true; used[k][belong[k]] = used[belong[k]][k] = true; for(int j = 1; j <= n; j++) { if(vis[j] == false && low[j] > cost[k][j]) { low[j] = cost[k][j]; belong[j] =k; } } ans += MIN; } return ans; } void Methord() { int ans = Prim(); int MIN = inf; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i != j && used[i][j] == false && cost[i][j] != inf) { MIN = min(MIN,ans - cost[i][belong[i]] + cost[i][j]); if(MIN < ans) MIN = inf; MIN = min(MIN,ans - cost[j][belong[j]] + cost[i][j]); if(MIN < ans) MIN = inf; } } if(MIN == ans) cout<<"Not Unique!"<<endl; else cout<<ans<<endl; } int main() { int t; cin>>t; while(t--) { int a,b,l; cin>>n>>m; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) cost[i][j] = inf; for(int i = 1; i <= m; i++) { cin>>a>>b>>l; cost[a][b] = cost[b][a] = l; } Methord(); } return 0; }