Codeforces 1228D. Complete Tripartite

传送门

不妨设 $1$ 号点在集合 $1$ 里

那么对于其他点,有且只有所有和 $1$ 没有边的点都在集合 $1$ 里

考虑不在集合 $1$ 的任意一个点 $x$ ,不妨设它在集合 $2$ 里

那么所有不在集合 $1$ 的,和 $x$ 没有边的点都在集合 $2$ 里,剩下的点都一定在集合 $3$ 里

所以集合划分完毕,然后就是判断合法性了,特判当然是越多越好啦!

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=6e5+7;
int n,m,bel[N],cnt[4];
int fir[N],from[N<<1],to[N<<1],cntt;
inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
int fa[N];
inline int find(int x) { return x!=fa[x] ? fa[x]=find(fa[x]) : x; }
int main()
{
    n=read(),m=read(); int a,b;
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++)
    {
        a=read(),b=read();
        add(a,b); add(b,a); fa[find(a)]=find(b);
    }
    bel[1]=1; cnt[1]++;
    for(int i=2;i<=n;i++)
    {
        bool GG=0;
        for(int j=fir[i];j;j=from[j])
        {
            int &v=to[j]; if(v==1) GG=1;
        }
        if(!GG&&!bel[i]) bel[i]=1,cnt[1]++;
    }
    int x=0;
    for(int i=fir[1];i;i=from[i])
    {
        x=to[i]; break;
    }
    bel[x]=2; cnt[2]++;
    for(int i=1;i<=n;i++)
    {
        bool GG=0; if(bel[i]) continue;
        for(int j=fir[i];j;j=from[j])
        {
            int &v=to[j]; if(v==x) GG=1;
        }
        if(!GG) bel[i]=2,cnt[2]++;
        else bel[i]=3,cnt[3]++;
    }
    for(int i=1;i<=3;i++) if(!cnt[i]) { printf("-1
"); return 0; }
    if(cnt[1]*cnt[2]+cnt[2]*cnt[3]+cnt[1]*cnt[3]!=m) { printf("-1
"); return 0; }
    for(int i=1;i<=n;i++)
    {
        if(find(i)!=find(1)) { printf("-1
"); return 0; }
        int tot=0,res=0; if(!bel[i]) { printf("-1
"); return 0; }
        for(int j=fir[i];j;j=from[j])
        {
            int &v=to[j]; if(bel[v]==bel[i]) { printf("-1
"); return 0; }
            tot++;
        }
        for(int j=1;j<=3;j++) if(bel[i]!=j) res+=cnt[j];
        if(tot!=res) { printf("-1
"); return 0; }
    }
    for(int i=1;i<=n;i++) printf("%d ",bel[i]);
    puts(""); return 0;
}
原文地址:https://www.cnblogs.com/LLTYYC/p/11612340.html