其他分享
首页 > 其他分享> > CF #805(div3) F - Equate Multisets 并查集+二分图?

CF #805(div3) F - Equate Multisets 并查集+二分图?

作者:互联网

给定若干个点对,每个点对包含的数字均在1-n之间

要求把这些点对分到两个set里面,使得每个set里面的n不重复

(话说我的第一反应是2-set然后慌张自己2-set不会打嘿嘿嘿)

一般这种匹配,冲突,点,都和图论有点关系

和图论有点关系就是要建图啦

俺的建图是把数字看成一个节点,如果存在点对,比如(1,2),则在1和2之间连边

然后玩一下样例,发现如果存在奇数环(环的长度为奇数),必然无解

我先写了个dfs判断环,但由于太久没码,码力down~down,挂了

遂怒写并查集,如果两个点之间有边,直接合并起来,如果集合的个数都是偶数,就有解(和dfs其实是一样的,本质是判断有没有奇数环)

 

 

#include<bits/stdc++.h>
using namespace std;
int n,fa[3*100007],sum[3*100007],book[3*100007];
int find(int u)
{
    if(fa[u]!=u) return fa[u]=find(fa[u]);
    else return u;
}
void init()
{
    for(int i=1;i<=n;i++) {
       fa[i]=i;sum[i]=1;book[i]=0;    
    }
}
int main()
{int t;
 
  //freopen("lys.in","r",stdin);
  
cin>>t;
while(t--)
{
    cin>>n;
    init();
    for(int i=1;i<=n;i++)
    {
        int a,b;
        cin>>a>>b;
        book[a]++;book[b]++;
        int f1=find(a),f2=find(b);
        if(f1!=f2)
        {
            fa[f1]=f2;
            sum[f2]+=sum[f1];
        }
    }
    
    int ok=0;
    for(int i=1;i<=n;i++)
    {
        if(book[i]>2) {
            ok=1;
            cout<<"NO"<<endl;
            break;
        }
    }
   if(ok==1) continue;
   
    ok=0;
    for(int i=1;i<=n;i++)
    {
        int f=find(i);
    //    cout<<i<<" "<<f<<" "<<sum[f]<<endl;
        if(sum[f]%2==1) 
        {
            ok=1;
        }
    }
    if(ok==0) {
        cout<<"YES"<<endl;
    }
    else {
        cout<<"NO"<<endl;
    }
}
    
}

 

标签:f1,f2,set,int,Multisets,查集,CF,fa,find
来源: https://www.cnblogs.com/liyishui2003/p/16467853.html