Codeforces Round #589 (Div. 2) D. Complete Tripartite(模拟)

题意:给你n个点 和 m条边 问是否可以分成三个集合 使得任意两个集合之间的任意两个点都有边

思路:对于其中一个集合v1 我们考虑其中的点1 假设点u和1无边 那么我们可以得到 u一定和点1在一个集合 否则将输出-1 所以我们可以暴力把所有的点先尽可能的分类 最后判断是否可行

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const int N = 3e5+7;
typedef long long ll;
const ll mod = 1e9+7;
using namespace std;
int u[N],v[N];
int col[N];
map<int,int> mm[N];
set<int> s[4];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int n,m; cin>>n>>m;
    for(int i=1;i<=m;i++){
        cin>>u[i]>>v[i];
        mm[u[i]][v[i]]=1;
        mm[v[i]][u[i]]=1;
    }
    
    int tot=0;
    for(int i=1;i<=n;i++){
        if(!col[i]){
            tot++;
            col[i]=tot;
            if(tot>3){
                cout<<"-1"<<endl;
                return 0;
            }
            s[tot].insert(i);
            for(int j=i+1;j<=n;j++){
                if(mm[i].count(j)) continue;
                if(col[j]) continue;
                col[j]=tot;
                s[tot].insert(j);
            }
        }
    }
    if(tot!=3){
        cout<<"-1"<<endl;
        return 0;
    }
    for(int i=1;i<=m;i++){
        if(col[u[i]]==col[v[i]]){
            cout<<"-1"<<endl;
            return 0;
        }
    }
    ll a,b,c; a=s[1].size(); b=s[2].size(); c=s[3].size();
    if(a*b+b*c+a*c!=m){
        cout<<"-1"<<endl;
        return 0;
    }
    for(int i=1;i<=n;i++)
        cout<<col[i]<<" ";
    cout<<endl; 
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/wmj6/p/11611001.html