题目地址:https://codeforces.com/contest/1228/problem/D
题意:给你n个点,m条边,能否构成三分图,每条边都要用上
思路:分三个集合f1、f2、f3,与f1、f2相连但与f3不相连的,与f2、f3相连但与f1不相连的,与f1、f3相连但与f2不相连的。三分图的原因,可以直接取点1作为集合一的一个点a1,再取与1相连的第一个点作为第二个集合的点a2,接着找到与点一点二都相连的点a3。然后就是遍历所有的点,分类到三个集合中去,检测所得的三分图的边是否与m相同和每个集合里的边是否有相连的即可。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 typedef long long ll; 8 const int MAXN=1e5+5; 9 int n,m; 10 vector<int>a[MAXN]; 11 void sol(){ 12 if(a[1].size()==0){ 13 cout<<"-1"; 14 return ; 15 } 16 int f1=1,f2=0,f3=0; 17 int color[MAXN]; 18 memset(color,0,sizeof(color)); 19 f2=a[f1][0]; 20 color[1]=1; 21 color[a[f1][0]]=2; 22 for(int j=1;j<=n;j++){ //找到f2和f3 23 bool a1=false,a2=false; 24 for(int i=0;i<a[j].size();i++){ 25 if(a[j][i]==f1) a1=true; 26 if(a[j][i]==f2) a2=true; 27 } 28 if(a1&&a2){ 29 f3=j; 30 break; 31 } 32 } 33 if(!f3){ //若没有f3则直接输出-1 34 cout<<"-1"; 35 return ; 36 } 37 color[f3]=3; 38 for(int i=1;i<=n;i++){ //分到各个集合里 39 int a1=0,a2=0,a3=0; 40 for(int j=0;j<a[i].size();j++){ //检测i点与f1,f2,f3那些点相连 41 if(a[i][j]==f1) a1=1; 42 if(a[i][j]==f2) a2=1; 43 if(a[i][j]==f3) a3=1; 44 } 45 if(a1+a2+a3!=2){ //若不是与其中两个点相连则直接输出-1 46 cout<<"-1"; 47 return ; 48 } 49 if(a1&&a2&&!a3) color[i]=3; 50 if(a1&&!a2&&a3) color[i]=2; 51 if(!a1&&a2&&a3) color[i]=1; 52 } 53 int cnt[4]={0}; 54 for(int i=1;i<=n;i++) cnt[color[i]]++; 55 if(cnt[1]*cnt[2]+cnt[2]*cnt[3]+cnt[3]*cnt[1]!=m){ //计算边的数量是否为m 56 cout<<"-1"; 57 return ; 58 } 59 for(int i=1;i<=n;i++){ //回路判断,检查每个集合里是否有相连的 60 for(int j=0;j<a[i].size();j++){ 61 if(color[i]==color[a[i][j]]){ 62 cout<<"-1"; 63 return ; 64 } 65 } 66 } 67 for(int i=1;i<=n;i++) 68 cout<<color[i]<<" "; 69 } 70 int main(){ 71 cin>>n>>m; 72 int x,y; 73 for(int i=0;i<m;i++){ 74 cin>>x>>y; 75 a[x].push_back(y); 76 a[y].push_back(x); 77 } 78 sol(); 79 return 0; 80 }
其中检测边的步骤,我试过去检测每个点是否都用上了,但WA了,有点懵。
Codeforces Round #589 (Div. 2) D. Complete Tripartite
原文:https://www.cnblogs.com/xunzf0402/p/11679911.html