真真假假

郭靖成为丐帮首领,他要去见丐帮的各位长老,但是长老们对他并不服气,所以,他们决定要给郭靖一个下马威。现在丐帮共有n名长老,他们每个人将扮演一个角色,要么是说谎者,要么是老实人。其中,
如果扮演说谎者,则他说的是假话。
如果扮演老实人,则他说的是真话。
长老之间知道每个人扮演的是什么角色。他们见到郭靖后,每个人向郭靖介绍其他长老,他们介绍的形式如下:
k r 1:表示k说r是老实人
k r 0:表示k说r是说谎者
这些介绍把郭靖弄糊涂了,他只好匆匆记下每个长老的话。现在请你帮助郭靖看看到底谁说的是真话,谁说的是假话。或者长老们自己也搞糊涂了吗,根本无法确定说是说谎者,谁是老实人。

输入格式:
第一行有一个整数L,表示共有L个测试组。(1≤L≤30)
其中每个测试组的第一行有两个整数n和m(1≤n≤10​5,1≤m≤10​5)。 随后的m行,每行有三个整数k,r,w(1≤k,r≤n,w={0,1})。

输出格式:
输出L行,每行为一个测试组结果。如果可以确定每个人的角色,则输出n个“0”和“1”构成的字符串,第i位为“0”表示第i位长老是说谎者,为“1”表示第i位长老是老实人。
如果根据测试组数据无法确定每位长老的角色,则输出“-1”。

输入样例:
在这里给出一组输入。例如:

2  
5 4  
1 2 1  
2 3 0  
2 4 0  
1 5 0  
3 3  
1 2 1  
1 3 0  
2 3 1

输出样例:
在这里给出相应的输出。例如:

00111
-1
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int pre[N<<1],num[N<<1],vis[N<<1],ans[N];
int n,m;
int find(int x){
	return x==pre[x]?pre[x]:pre[x]=find(pre[x]);
}
void merge(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	{
		pre[fx]=fy;
		num[fy]+=num[fx];
	}
}
void solve()
{
	for(int i=1;i<=n;i++)
	{
		int fx=find(i);
		int fy=find(i+n);
		if(fx==fy)
		{
			printf("-1\n");
			return ;
		}
		if(vis[fx]==0)
		{
			if(num[fx]>num[fy])
			{
				vis[fx]=1;
				vis[fy]=-1;
			}
			else
			{
				vis[fx]=-1;
				vis[fy]=1;
			}
		}
		ans[i]=(vis[fx]==1);
	}
	for(int i=1;i<=n;i++)
	    printf("%d",ans[i]);
	printf("\n");
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=1;i<=2*n;i++)
		{
			pre[i]=i;
			num[i]=(i<=n);
			vis[i]=0;
		}
		for(int i=1;i<=m;i++)
		{
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			if(w==1)
			{
				merge(u,v);
				merge(u+n,v+n);
			}
			else
			{
				merge(u,v+n);
				merge(u+n,v);
			}
		}
		solve();
	}	
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全能战士s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值