最小生成树唯一性判断-UESTC1959天才钱vs学霸周

天才钱vs学霸周

Time Limit: 1000 MS     Memory Limit: 256 MB
Submit Status

有一天,天才钱学霸周闲的无聊玩起了游戏,游戏内容是这样的,现在有nn个城堡 mm个不同的桥,每一个桥连接着两个不同的城堡,并且已知这mm个桥可以使nn个城堡连通,此外每一个桥都有重量vv。两位大爷需要给出选择桥的方案使得所有城堡被连通,注意两位大爷的方案不能完全相同(至少存在一个桥不相同),已知周大爷优先给出方案(因此钱大爷的方案必须不同于周大爷)。规则很诡异,如果钱大爷的方案中桥的重量之和周大爷的方案中桥的重量之和,那么钱大爷获胜,反之周大爷获胜。两位大爷都很聪明,他们会给出最优方案。现在你需要计算谁会赢。

Input

第一行输入两个值nn2n20002≤n≤2000),mm (nm200000n≤m≤200000) 接下来mm行,每一行输入三个值aa (1an1≤a≤n),bb(1bn1≤b≤n),vv(1v10181≤v≤1018),其中a!=ba!=b

Output

如果钱大爷获胜输出“zin”,反之输出“ogisosetsuna” 。

Sample input and output

Sample InputSample Output
2 2
1 2 1
1 2 1
zin

Hint

样例和test1不同

Source

2018 UESTC ACM Training for Graph Theory            
题解:其实就是最小生成树唯一性的判定Orz......;












 利用并查集,按边权从小到大排序,然后对于每一个权值对应的边,先查找边的两个点不在同一集合的数量cnt1,然后再边枚举每一条不在同一集合的,并将边的两点合并到同一集合,计算数量cnt2,,对于每一权值,如果有cnt1>cnt2这说明最小生成树不唯一。

AC代码为:

#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

typedef long long LL;
const int N=2000+10;
const int M=200000+10;
int fa[N];
map<LL,int> mm;
vector<int> E[M];

struct node{
    int u,v;
    LL w;
}edge[M];

bool cmp(node a,node b)
{
    return a.w<b.w;
}

void init()
{
    for(int i=0;i<N;i++) fa[i]=i;
}

int fi(int x)
{
    return x==fa[x]?x:fa[x]=fi(fa[x]);
}

void Union(int x,int y)
{
    int fx=fi(x),fy=fi(y);
    if(fx!=fy) fa[fx]=fy;
}

int main()
{
    init();
    int n,m,cnt=1;
    int cnt1=0,cnt2=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d%lld",&edge[i].u,&edge[i].v,&edge[i].w);
    sort(edge+1,edge+1+m,cmp);
    for(int i=1;i<=m;i++){
        if(!mm[edge[i].w]) mm[edge[i].w]=cnt,cnt++;
        int pos=mm[edge[i].w];
        E[pos].push_back(i);
    }
    for(int i=1;i<cnt;i++)
	{
        for(int j=0;j<E[i].size();j++)
		{
            int pos=E[i][j];
            if(fi(edge[pos].u)!=fi(edge[pos].v)) cnt1++;
        }
        for(int j=0;j<E[i].size();j++)
		{
            int pos=E[i][j];
            if(fi(edge[pos].u)!=fi(edge[pos].v))
			{
                Union(edge[pos].u,edge[pos].v);
                cnt2++;
            }
        }
        if(cnt1>cnt2) break;
    }
    if(cnt1>cnt2) printf("zin
");
    else printf("ogisosetsuna
");
    return 0;
}

原文地址:https://www.cnblogs.com/csushl/p/9386530.html