D. Complete Tripartite - 补题

D. Complete Tripartite

传送门

思路

题目实际上是三分图的问题,即给出一个图要求得出三分图的结果,如果得不到输出-1。
首先考虑三个集合的选取:我们可以直接让第1个点(点x)为集合1,(如果此点是孤立点则无法构成三分图,输出-1即可),然后在此点的邻接点中任意选出1个点(点y)作为集合2,最后筛选这两个点的公共邻接点,若不存在则无法构成三分图,直接输出-1,找到公共点(点z)后作为集合3。
完成3个集合的选取后,遍历所有点判断它的所有邻接点是否存在x,y,z中的两个,若不满足则无法构成三分图(因为三分图每个集合的点和其他集合中的所有点都邻接,但是与自己集合中的点都不邻接),满足条件就将其染成缺失的点所在集合的颜色。
完成染色后判断总边数是否满足条件,根据三分图的定义可以得到这个三分图的边数:3个集合的元素个数两两相乘再求和就是总边数,判断是否等于给出的m
最后判断每个点相邻的顶点中是否存在与自己颜色相同的点,若存在则不满足定义输出-1。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std; 

const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N=1e5+7;
const ll mod=1e9+7;    

vector<int>u[N];
int color[N];
int vis[N],flag=1;

int main(){ 
    IO;
    int t=1;
    //cin>>t;
    while(t--){ 
        int n,m;
        cin>>n>>m;
        for (int i = 0; i < m; ++i)
        {
            int x,y;
            cin>>x>>y;
            u[x].push_back(y);
            u[y].push_back(x);
        } 
        color[1]=1;
        int x=1,y=0,z=0;
        for (auto i:u[x])
        {
            y=i;
            break;
        }
        if(!y){
            cout<<-1<<endl;
            continue;
        }
        for (auto i:u[x])
        {
            for (auto j:u[y])
            {
                if(i!=x&&i!=y&&i==j){
                    z=i;
                    break;
                }
            }if(z)break;
        }
        if(!z){
            cout<<-1<<endl;
            continue;
        }
        for (int i = 1; i <= n; ++i)
        {
            int x1=0,x2=0,x3=0;
            for (auto j:u[i])
            {
                if(j==x)x1++;
                if(j==y)x2++;
                if(j==z)x3++;
            }
            if(x1+x2+x3!=2){
                cout<<-1<<endl;
                return 0;
            }
            if(x1&&x2&&!x3)color[i]=3;
            if(x1&&!x2&&x3)color[i]=2;
            if(!x1&&x2&&x3)color[i]=1;
        }int a[5]={0};
        for (int i = 1; i <= n; ++i)
        {
            a[color[i]]++;
        }
        if(a[1]*a[2]+a[1]*a[3]+a[2]*a[3]!=m){
            cout<<-1<<endl;
            continue;
        }
        for (int i = 1; i <= n; ++i)
        {
            for(auto j:u[i]){
                if(color[i]==color[j]){
                    cout<<-1<<endl;
                    return 0;
                }
            }
        }
        for (int i = 1; i <= n; ++i)
        {
            cout<<color[i]<<" ";
        }cout<<endl;
    }
    return 0;
}

判断条件有点多,搞得有点晕。
今天也要努力啊!!!

posted @ 2021-01-26 18:01  !^^!  阅读(67)  评论(0)    收藏  举报