题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5302
题意:给你一个无向图,它的边要么是黑色要么是白色,且图上的每个点最多与两个黑边两个白边相连。现在,Demon将图分成两部分,一部分包含所有的黑边,另一部分包括所有的白边,给你白边图中度为0的点的数量w0,度为1的点数w1,度为2的点数w2,与黑边图中度为0的点数b1,度为1的点数b1,度为2的点数b2,要你输出任意一个符合条件的原图,如果不能,输出-1
(注1:无论是黑边图,还是白边图,给出的度为0、1、2三种点的数量均>=1;
注2:w0+w1+w2==b0+b1+b2,输出图的点数最多为w0+w1+w2个;
注3:图中无重边,无自环;
解:构造题
考虑每条边对应两度,那么w1或b1为奇数一定无解
排除以上情况,有w1>=2 && b1>=2,将二度的点排成一排,顺次链接起来,然后将首尾分别和一个一度点相连,剩下的一度点两两互相连接即可
这样我们就可以解决黑图或白图,考虑上述构造方法每个点只和相邻的点连接,我们在构造完一图之后,另外一图只需要稍微打乱下点的顺序即可
for example:
1 2 3 4 5 -> 1 4 2 5 3
另外n==4的时候需要特判一下。。。
1 /* 2 * Problem: hdu5302 Connect the Graph 3 * Author: SHJWUDP 4 * Created Time: 2015/8/10 星期一 19:24:32 5 * File Name: 1006.cpp 6 * State: Accepted 7 * Memo: 构造 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <vector> 12 #include <cstring> 13 #include <algorithm> 14 15 using namespace std; 16 17 int main() { 18 #ifndef ONLINE_JUDGE 19 freopen("in", "r", stdin); 20 //freopen("out", "w", stdout); 21 #endif 22 int T; 23 scanf("%d", &T); 24 while(T--) { 25 vector<int> w(3), b(3); 26 for(int i=0; i<3; i++) scanf("%d", &w[i]); 27 for(int i=0; i<3; i++) scanf("%d", &b[i]); 28 if((w[1] & 1) || (b[1] & 1)) { 29 puts("-1"); continue; 30 } 31 int n=w[0]+w[1]+w[2]; 32 if(n<=4) { 33 puts("4\n1 2 0\n1 3 0\n2 3 1\n3 4 1"); continue; 34 } 35 int m1=w[2]+w[1]/2; 36 int m2=b[2]+b[1]/2; 37 printf("%d\n", m1+m2); 38 int nw=1; 39 w[2]++; 40 while(w[2]--) { 41 printf("%d %d 0\n", nw, nw+1); nw++; 42 } 43 w[1]-=2; nw++; 44 while(w[1]) { 45 printf("%d %d 0\n", nw, nw+1); nw+=2; 46 w[1]-=2; 47 } 48 vector<int> table(n+1); 49 int pos=1; 50 for(int i=1; i<=n; i+=2) table[pos++]=i; 51 for(int i=2; i<=n; i+=2) table[pos++]=i; 52 int nb=1; 53 b[2]++; 54 while(b[2]--) { 55 printf("%d %d 1\n", table[nb], table[nb+1]); nb++; 56 } 57 b[1]-=2; nb++; 58 while(b[1]) { 59 printf("%d %d 1\n", table[nb], table[nb+1]); nb+=2; 60 b[1]-=2; 61 } 62 } 63 return 0; 64 }