拦住我的好题
题意:
- 给定一个无向图, 要求在其中找三个点集, 使得这三个点集 使得每个点集 都与其他的点集有连边 (三分图)
数据范围:
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
n≤3∗105,m≤min(3∗105,2n∗(n−1))≤1e6
前置技能:无
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;
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())
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 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;
}