Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 26256 | Accepted: 9374 |
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!
Source
题目大意:对于给定的n个点,和m条边,如果只有唯一的一个最小生成树存在,输出最小生成树的边权值和,否则输出Not Unique!
思路:
本题的AC思路主要是从FZU 2087的AC思路来的。(连接:http://acm.fzu.edu.cn/problem.php?pid=2087)
我们模拟最小生成树的克鲁斯卡尔算法,先将所有边排序,然后在树没有完全生成完毕之前,将可行边贪心的加入树中,这样我们不难想出,如果这样生成的最小生成树不唯一,辣么一定是有重边权的边,而且符合入树规则(简单的说就是不能成环,并且这两个点之间未连通被~)。
在克鲁斯卡尔算法过程中,判断是否符合入树规则的代码我们是这样来实现的:
for(int i=0;i<m;i++)//遍历m条边 { if(find(a[i].x)!=find(a[i].y))//如果能够入树 { merge(a[i].x,a[i].y);//联通这两个点 output+=a[i].w;//加上这条边的权值。 } }那么我们刚刚推出的结论:如果存在不唯一的最小生成树,辣么要有贪心过程中存在的重边权值的边存在,并且要符合入树规则,辣么我们实现代码可以变成这样:
sort(a,a+m,cmp); int output=0;//现在这个output不是用来加和边权值的,而是统计生成树的边数的。 int j; for(int i=0;i<m;i=j) { for(j=i;a[i].w==a[j].w;j++)//如果没有重边权值的边存在,辣么过程只进行一次,否则如果有重边权值的边存在,要判断是否符合入树规则,如果有一条边符合,辣么就说明还有另外一条边可以入树。 { if(find(a[j].x)!=find(a[j].y)) { output++; } } for(j=i;a[i].w==a[j].w;j++) { if(find(a[j].x)!=find(a[j].y)) { merge(a[j].x,a[j].y);//当然少不了合并。 } } }
根据生成树的规则,我们知道其边总数一定是n-1,辣么这个时候我们其实只要判断一下output是否等于n-1就行,如果是等于n-1的,那么就只存在唯一的一颗最小生成树,然后我们再用克鲁斯卡尔算法计算一下总边权值即可。
这样我们就完整的清晰了代码思路,最后上完整的AC代码:#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int f[1050]; struct path { int x,y,w; }a[10050]; int n,m; int ans; int cmp(path a,path b) { return a.w<b.w; } int find(int x) { return f[x] == x ? x : (f[x] = find(f[x])); } void merge(int a,int b) { int A,B; A=find(a); B=find(b); if(A!=B) f[B]=A; } void MST() { ans=0; for(int i=1;i<=n;i++)f[i]=i; for(int i=0;i<m;i++) { if(find(a[i].x)!=find(a[i].y)) { ans+=a[i].w; merge(a[i].x,a[i].y); } } return ; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { f[i]=i; } for(int i=0;i<m;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w); } sort(a,a+m,cmp); int output=0; int j; for(int i=0;i<m;i=j) { for(j=i;a[i].w==a[j].w;j++) { if(find(a[j].x)!=find(a[j].y)) { output++; } } for(j=i;a[i].w==a[j].w;j++) { if(find(a[j].x)!=find(a[j].y)) { merge(a[j].x,a[j].y); } } } MST(); if(output==n-1) printf("%d\n",ans); else printf("Not Unique!\n"); } }