牛客小白月赛24 H.人人都是好朋友(离散化&并查集)
思路:将朋友的关系建立一个并查集。再遍历一遍,看两个敌人的根结点是否相同。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
#define mst(a) memset(a,0,sizeof a)
int s[N<<1],a[N],b[N],d[N<<1],h[N<<1];
int c[N];
int find(int x){
if(x!=s[x]) s[x]=find(s[x]);
return s[x];
}
void union_set(int x,int y){
x=find(x),y=find(y);
if(h[x]==h[y]){
h[y]++;
s[x]=y;
}
else h[x]>h[y]?s[y]=x:s[x]=y;
}
int read(){ //快读
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int main(){
int t;
t=read();
while(t--){
int n,k=0;
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read(),b[i]=read(),c[i]=read();
d[++k]=a[i],d[++k]=b[i];
s[i]=i,s[i+n]=i+n,h[i]=h[i+n]=0;
}
sort(d+1,d+k+1);//排序后离散化
int cnt=unique(d+1,d+k+1)-d;
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(d+1,d+cnt+1,a[i])-d;
b[i]=lower_bound(d+1,d+cnt+1,b[i])-d;
}
for(int i=1;i<=n;i++)
if(c[i]) union_set(a[i],b[i]); //将所有友好关系建立一个并查集.
int f=1;
for(int i=1;i<=n;i++)
if(!c[i]&&s[a[i]]==s[b[i]]) //找矛盾的即可
{
f=0;
break;
}
puts(f?"YES":"NO");
}
return 0;
}