ABC第四题我用集合(类似并查集)+map映射(本质是哈希)做,然后挂了:
#include<bits/stdc++.h>
using namespace std;
int dot[200005],n,m,x,y;
int sets[200005],sdots[200005];
map<pair<int,int>,bool>edge;
void date(int x){
int tmp=x;
do{
tmp=dot[tmp];
sdots[tmp]++;//集合中增加一个点
sets[tmp]++;//增加一条边
//cout<<tmp<<":"<<sets[tmp]<<"\n\n";
dot[x]=tmp;
}while(dot[tmp]!=tmp);
}
void update(int x){
int tmp=x;
do{
tmp=dot[tmp];
if(dot[x]!=dot[tmp])sdots[tmp]++;//集合中增加一个点
//cout<<tmp<<":"<<sets[tmp]<<"\n\n";
dot[x]=tmp;
}while(dot[tmp]!=tmp);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
memset(dot,-1,sizeof(dot));
cin>>n>>m;
while(m--){
cin>>x>>y;
dot[y]=x;
if(edge[pair<int,int>(x,y)]==1||edge[pair<int,int>(x,y)]==1)continue;//重边,不做任何改动
if(dot[x]==-1)dot[x]=x;//注意一定要先更新x,否则会无限递归
date(y);//更新y的祖先,表明x和y在同一集合
edge[pair<int,int>(x,y)]=1;
}
//for(int i=1;i<=n;i++)cout<<i<<"::"<<dot[i]<<" ";
for(int i=1;i<=n;i++){
if(dot[i]==-1){
cout<<"No";
return 0;
}
update(i);//最后还要再更新一次,但不加边了
}
//for(int i=1;i<=n;i++)cout<<sets[i]<<" "<<sdots[i]<<"\n";
for(int i=1;i<=n;i++){
if(dot[i]!=i)continue;//不是集合的祖先,不管他
if(sets[i]!=sdots[i]){//不满足条件
cout<<"No";
return 0;
}
}
cout<<"Yes";
}//极端情况会退化成一条链,这里应该不会吧
求调/kk