题意:
无向简单图,无自环,无重边,n个点,m条边,请你将这n个点分为3个互相没有交集的集合。并且满足以下条件:
1.同一个集合中的任意两点之间没有边。
2.每个点都要与除了它这个集合以外的所有点相连。
没有答案就输出-1,多种答案输出任意一种。
思路:
用hash值代表与一个点相连的 都有哪些点,
如果出现三种hash值就没有答案;
如果有一个点的度为0,也没有答案;
根据哈希值,点被分为三份,如果每一份的点数+它们所连的点的点数 != n,也没有答案;
如果同一条边相连的两个点的哈希值相同,也没有答案。
以上条件都不满足的话,就是答案,输出即可。
代码:
#include <stdio.h> #include <queue> #include <string> #include <string.h> #include <algorithm> #include <math.h> #include <map> #include <set> #include <iostream> using namespace std; typedef long long int ll; const int maxn = 1e5 + 10; const int inf = 70000000; const ll mod = 1e9 + 7; const ll seed = 131; vector<int>mp[maxn]; map<ll,int>s; ll a[maxn]; int p[maxn]; ll _hash[maxn]; int main() { int n,m,x,y,num; while(scanf("%d%d",&n,&m) != EOF){ s.clear(); num = 0; for(int i = 1;i <= m;i++){ scanf("%d%d",&x,&y); mp[x].push_back(y); mp[y].push_back(x); } for(int i = 1;i <= n;i++){ sort(mp[i].begin(),mp[i].end()); ll temp = 0; for(int j = 0;j < mp[i].size();j++){ temp = ((temp * seed) % mod + mp[i][j]) % mod; } _hash[i] = temp; if(s[temp] == 0){ num++; a[num] = temp; p[num] = i; } s[temp]++; if(temp == 0 || num > 3){ printf("-1 "); return 0; } } for(int i = 1;i <= 3;i++){ if(s[a[i]] + mp[p[i]].size() != n){ printf("-1 "); return 0; } } for(int i = 1;i <= n;i++){ for(int j = 0;j < mp[i].size();j++){ x = i; y = mp[i][j]; if(_hash[x] == _hash[y]){ printf("-1 "); return 0; } } } for(int i = 1;i <= n;i++){ if(_hash[i] == a[1]) printf("1 "); else if(_hash[i] == a[2]) printf("2 "); else printf("3 "); } puts(""); } return 0; }