cf-1228D. Complete Tripartite

拦住我的好题

题意:

  • 给定一个无向图, 要求在其中找三个点集, 使得这三个点集 使得每个点集 都与其他的点集有连边 (三分图)

数据范围: n ≤ 3 ∗ 1 0 5 , m ≤ m i n ( 3 ∗ 1 0 5 , n ∗ ( n − 1 ) 2 ) ≤ 1 e 6 n\leq 3*10^5, m\leq min(3*10^5, \frac{n*(n-1)}{2}) \leq1e6 n3105,mmin(3105,2n(n1))1e6

>> face <<

前置技能:无

Tutorial: 注意到可以任意枚举第一个点, 然后与该点不直接相连的没有访问过的点都可以放入该集合中, 该过程可以使用vector<set> 来使用, 迅速判断有没有点直接相连

#include <bits/stdc++.h>
#include <bits/extc++.h>

using namespace std;
#define _rep(n, a, b) for (ll n = (a); n <= (b); ++n)
#define _rev(n, a, b) for (ll n = (a); n >= (b); --n)
#define _for(n, a, b) for (ll n = (a); n < (b); ++n)
#define _rof(n, a, b) for (ll n = (a); n > (b); --n)
#define oo 0x3f3f3f3f3f3f
#define ll long long
#define db double
#define eps 1e-6
#define bin(x) cout << bitset<10>(x) << endl;
#define what_is(x) cerr << #x << " is " << x << endl
#define met(a, b) memset(a, b, sizeof(a))
#define mp(a, b) make_pair(a, b)
#define all(x) x.begin(), x.end()
#define pii pair<ll, ll>
#define pdd pair<db, db>
#define pi acos(-1.0)
const ll maxn = 3e5 + 10;
const ll mod = 1e9 + 7;
int n, m;
vector<set<int>> G(maxn);
signed main()
{
	cin >> n >> m;
	_rep(i, 1, m){
		int u, v;
		cin >> u >> v;
		G[u].insert(v);
		G[v].insert(u);
	}
	vector<int> group(n+1, -1);
	_for(g, 0, 3){
		int fir;
		//_rep(fir, 1, n)if(group[fir] == -1)break;
		for(fir = 1;fir <= n;fir++)if(group[fir] == -1)break;
		if(fir == n+1){
			return cout << -1 << endl, 0;
		}
		group[fir] = g;
		_rep(sec, 1, n) if(fir != sec && group[sec] == -1 && G[fir].find(sec) == G[fir].end())//没有和fir直接相连
			group[sec] = g;
	}

	vector<vector<int>> groups(3);
	_rep(cur, 1, n){
		if(group[cur] == -1)
			return cout << -1 << endl, 0;
		groups[group[cur]].push_back(cur);
	}

	bool okay = 1;
	// int s1 = groups[0].size(), s2 = groups[1].size(), s3 = groups[2].size();
	// if(s1 == 0 |bu| s2 == 0 || s3 == 0 || m != s1*s2 + s2*s3 + s1*s3)okay = 0;3
	int edges = 0;
	_for(g1, 0, 3){
		_for(g2, g1 + 1, 3){
			for(auto v1:groups[g1]){
				for(auto v2:groups[g2]){
					if(G[v2].find(v1) == G[v2].end())okay = 0;
					else edges++;
				}
			}
		}
	}
	okay &= (edges == m);
	if(okay)_rep(i, 1, n)cout << group[i] + 1 << " ";
	else cout << -1 << endl;
 

	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值