题目链接:
题目大意:
给出一张图中的一些信息。包括与0,1,2条黑边相连的点的个数,与0,1,2条白边相连的点的个数。构造出一个这样的图。
题目分析:
首先我们设a[i]为连有i条白边的点的个数,b[i]为连有i条黑边的点的个数。
所以我们容易得到结论,a[1]和b[1]都不能使奇数,因为两条边每条白边能够贡献出的度数为2,所以白边的总度数一定是偶数,如果度数为1的点的个数为奇数,那么总度数一定是奇数,就与白边的总度数矛盾了!!
黑边与白边同理。
我们可以通过构建出一条链,得到2个度数为1的点和全部的度数为2的点,因为给出度数为1的点不可能小于1,那么也就是最小值就是2,那么我们构建这条链一定是合理的。对于黑边,我们需要标记奇偶点,因为不存在重边,所以我们在建黑边的时候采用奇偶点连边的方式来防止出现重边。
最后剩下的度数为1的边,找两个点白边相邻连边,黑边奇偶点连边。
最后得到的这个图就是满足题意的一个构造。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 1000007
using namespace std;
int t;
int a[5],b[5];
int d[MAX];
int main ( )
{
scanf ( "%d" , &t );
while ( t-- )
{
for ( int i = 0 ; i < 3 ; i++ )
scanf ( "%d" , &a[i] );
for ( int i = 0 ; i < 3 ; i++ )
scanf ( "%d" , &b[i] );
//获得点的总个数
int sum = 0;
for ( int i = 0 ; i < 3 ; i++ )
sum += a[i];
if ( (a[1]&1) || (b[1]&1) )
{
puts("-1");
continue;
}
if ( sum == 4 )
{
puts("4\n1 2 0\n1 3 0\n2 3 1\n3 4 1");
continue;
}
printf ( "%d\n" , a[1]/2+a[2]+b[1]/2+b[2] );
int t = 1;
//利用链构建出白边度数都为2,只有两端的点都只是1
while ( a[2] != -1 )
{
printf ( "%d %d 0\n" , t , t+1 );
t++;
a[2]--;
}
t++;
//除了链两端的点构建出其他的白边读书为1的点
while ( a[1] != 2 )
{
printf ( "%d %d 0\n" , t , t+1 );
t += 2;
a[1] -= 2;
}
int tt = 0;
//得到奇数点和偶数点,因为不能有重边,所以利用黑边建图时两个间隔
for ( int i = 1 ; i <= sum ; i += 2 )
d[tt++] = i;
for ( int i = 2 ; i <= sum ; i += 2 )
d[tt++] = i;
t = 0;
//构造出黑边度数为2的点
while ( b[2] != -1 )
{
printf ( "%d %d 1\n" ,
min ( d[t] , d[t+1] ) , max ( d[t] , d[t+1]));
t++;
b[2]--;
}
t++;
//构建除了那条链的两个端点以外的点
while ( b[1]!= 2 )
{
printf ( "%d %d 1\n", min(d[t],d[t+1] ), max ( d[t],d[t+1]));
t += 2;
b[1] -= 2;
}
}
}