Logo tlxjy的博客

博客

求ABC题解

2023-03-04 21:43:49 By tlxjy

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

评论

tlxjy
好像就是并查集?

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。