题意:给你一个无向图,它的边要么是黑色要么是白色,且图上的每个点最多与两个黑边两个白边相连。现在,Demon将图分成两部分,一部分包含所有的黑边,另一部分包括所有的白边,给你白边图中度为0的点的数量w0,度为1的点数w1,度为2的点数w2,与黑边图中度为0的点数b1,度为1的点数b1,度为2的点数b2,要你输出任意一个符合条件的原图,如果不能,输出-1
无论是黑边图,还是白边图,给出的度为0、1、2三种点的数量均>=1 w0+w1+w2==b0+b1+b2,输出图的点数最多为w0+w1+w2个;图中无重边,无自环;
因为 只要白边或者 黑边 度数为1的点 为奇数个 就一定是无解的,因为每个点的白度数和黑度数至多为2,
那么最小是3个点 无解 4点的话 只剩 1 2 1 1 2 1 特判
接下来的 就构造
处理白色的时候 1 2 3 4 5..n 前w2 个分别连接,然后 接下来 从(w2,w2+1)(w2+2,w2+3)...(w2+w1-2,w2+w1-1) 然后再让最大的那个奇数和1相连,为何等等解释
处理黑色的时候1 3 5...2 4 6.... 依照上面的方法连接, 但是最后一条 就是选择 最后一个数和1相连,这样一定是一组解,因为我们排完相邻的不会有在之前相交(n>=5) 那么最大的偶数也不会和1相交,于是就得到解了
解释上面为何使用最大的奇数,就是为了让2和最大的奇数他们放在中间,尽量早的使用,在处理黑色的时候就不会产生无解了,因为最少有一个是没有黑色边度数的,最后一个和1连的 取最后一个便是,因为n>=5最后一个一定是大偶数也不会是2 那么就一定存在一组解
#include <iostream>
#include <algorithm> #include <cstdio>
using namespace std;
const int maxn=*;
int a[maxn];
int main()
{
int w0,w1,w2,b1,b0,b2;
int cas;
scanf("%d",&cas);
for(int cc=; cc<=cas; cc++)
{
scanf("%d%d%d%d%d%d",&w0,&w1,&w2,&b0,&b1,&b2);
if(w0==||w1==||w2==||b0==||b1==||b2==)while(true);
if(w1&||b1&){
puts("-1");continue;
}
int n=w0+w1+w2;
if(n==){
puts("");
puts("1 2 0");
puts("1 3 0");
puts("4 2 1");
puts("4 3 1");
continue;
}
printf("%d\n",(w1+w2*+b1+b2*)/ );
for(int i=;i<w2; i++)
printf("%d %d 0\n",i,i+);
for(int i=;i<w1-;i+=){
printf("%d %d 0\n",w2+i,w2+i+);
}
int id=(n-)/*+;
printf("%d %d 0\n",,id);
int cnt=;
for(int i=;i<=n; i+=){
a[cnt++]=i;
}
for(int i=;i<=n; i+=){
a[cnt++]=i;
}
for(int i=;i<b2-; i++)
printf("%d %d 1\n",a[i],a[i+]);
int d=;
for(int i=; i<b1-; i+=){
printf("%d %d 1\n",a[b2-+i],a[b2+i]);
d=max(d,b2+i);
}
for(int i=d+; ; i++)
if(a[i]!=id&&a[i]!=){
printf("%d %d 1\n",,a[i]);break;
}
}
return ;
}