题目大意:
给一个图,有n个节点m条路,问你是否存在唯一的最小生成树,并且不能存在环
那么,我们就要求次最小生成树,如果次最小生成树 == 最小生成树,那么就不是唯一的,输出Not Unique!
如果次最小生成树 > 最小生成树,则输出最小生成树加起来的权值
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 16477 | Accepted: 5713 |
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!
#include<iostream> #include<cstring> #include<algorithm> using namespace std; #define MAX 103 #define INF 1e9 struct node { int u,v,w; }edge[MAX*MAX]; int n,m; int father[MAX],MIN=0; int map[MAX]; bool cmp(struct node u,struct node v){ return u.w<v.w; } int find(int u){ return father[u]==u?u:father[u]=find(father[u]); } bool canUnion(int u,int v){ int a=find(u); int b=find(v); if(a==b)return false; else father[a]=b; return true; } bool kruskal(){ MIN=0; int sum=0;int index=0; for(int i=1;i<=n;++i)father[i]=i; for(int i=1;i<=m;++i){/*先求出最小生成树 */ if(canUnion(edge[i].u,edge[i].v)){ MIN+=edge[i].w;map[++index]=i;/*map记录了那些边被用在最小生成树中*/ } } int cnt=0;int secondMIN=INF; for(int i=1;i<=index;++i){//每次 sum=0;cnt=0; for(int j=1;j<=n;++j)father[j]=j; for(int j=1;j<=m;++j) { if(map[i]==j)continue;//每次去掉最小生成树上的边map[i] if(canUnion(edge[j].u,edge[j].v)) { sum+=edge[j].w; cnt++; } } if(cnt!=n-1)sum+=INF; if(secondMIN>sum)secondMIN=sum;//secondMIn保留了次最小生成树的值 } if(secondMIN==MIN)return false; else return true; } int main(int argc, char *argv[]) { int t;cin>>t; for(int i=0;i<t;++i){ cin>>n>>m; for(int j=1;j<=m;++j) cin>>edge[j].u>>edge[j].v>>edge[j].w; sort(edge+1,edge+1+m,cmp); if(kruskal())cout<<MIN<<endl; else cout<<"Not Unique!"<<endl; } return 0; }