| Time Limit: 1000MS | Memory Limit: 10000K | |
| Total Submissions: 16068 | Accepted: 5566 |
Description
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
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
思路:按并查集,先解出第一次的最小树,然后标记所有用过的边,和所具有相同权值的边。然后依次删除用过的具有相同权值的边,看最小生成树的值是不是一样,一样则最 小树不唯一。
易错点:权值全为0 要注意。
2
3 2
1 2 0
2 3 0
3 3
1 2 0
2 3 0
1 3 0
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int mm=110000;
const int oo=1e9;
int root[mm],ran[mm];
class node
{
public:int u,v,c;
bool used,equ,del;
node(){used=equ=del=0;}
}edge[mm];
int m,n,cen;
bool cmp(node a,node b)
{
return a.c<b.c;
}
int look(int x)
{
if(x^root[x])root[x]=look(root[x]);
return root[x];
}
void uni(int x,int y)
{
if(ran[look(x)]>ran[look(y)])root[look(y)]=look(x),ran[look(x)]+=ran[look(y)];
else root[look(x)]=look(y),ran[look(y)]+=ran[look(x)];
}
int kruskal()
{ cen++;int sum=0,num=0;
for(int i=0;i<m;i++)
{
if(edge[i].del)continue;
if(look(edge[i].u)^look(edge[i].v))
{uni(edge[i].u,edge[i].v);
sum+=edge[i].c;num++;
if(cen==1)
edge[i].used=1;
}
if(num>=n-1)break;
}
if(num<n-1)return -oo;///不能构成最小树
return sum;
}
void _set()
{
for(int i=0;i<=n;i++)
root[i]=i,ran[i]=1;
}
int main()
{
int cas;
while(cin>>cas)
{ while(cas--)
{ memset(edge,0,sizeof(edge));
cin>>n>>m;
for(int i=0;i<m;i++)
{
cin>>edge[i].u>>edge[i].v>>edge[i].c;
}
for(int i=0;i<m;i++)
for(int j=0;j<m;j++)
if(i^j&&edge[i].c==edge[j].c)
edge[i].equ=edge[j].equ=1;
sort(edge,edge+m,cmp);
_set();int ans=0,z;
cen=0;ans=kruskal();
///if(ans==-oo)ans=0;
bool flag=1;
for(int i=0;i<m;i++)
{
if(edge[i].used&&edge[i].equ)
{ _set();
edge[i].del=1;z=kruskal();edge[i].del=0;
if(z==ans){flag=0;break;}
}
}
if(!flag)cout<<"Not Unique!\n";
else cout<<ans<<"\n";
}
}
}
1万+



被折叠的 条评论
为什么被折叠?



