您的位置:首页 > 其它

hdu5302 构造

2015-10-02 17:46 316 查看
题意:给你一个无向图,它的边要么是黑色要么是白色,且图上的每个点最多与两个黑边两个白边相连。现在,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=2000*3;
int a[maxn];
int main()
{
int w0,w1,w2,b1,b0,b2;
int cas;
scanf("%d",&cas);
for(int cc=1; cc<=cas; cc++)
{
scanf("%d%d%d%d%d%d",&w0,&w1,&w2,&b0,&b1,&b2);
if(w0==0||w1==0||w2==0||b0==0||b1==0||b2==0)while(true);
if(w1&1||b1&1){
puts("-1");continue;
}
int n=w0+w1+w2;
if(n==4){
puts("4");
puts("1 2 0");
puts("1 3 0");
puts("4 2 1");
puts("4 3 1");
continue;
}
printf("%d\n",(w1+w2*2+b1+b2*2)/2 );
for(int i=1;i<w2; i++)
printf("%d %d 0\n",i,i+1);
for(int i=0;i<w1-1;i+=2){
printf("%d %d 0\n",w2+i,w2+i+1);
}
int id=(n-1)/2*2+1;
printf("%d %d 0\n",1,id);
int cnt=0;
for(int i=1;i<=n; i+=2){
a[cnt++]=i;
}
for(int i=2;i<=n; i+=2){
a[cnt++]=i;
}
for(int i=0;i<b2-1; i++)
printf("%d %d 1\n",a[i],a[i+1]);
int d=0;
for(int i=0; i<b1-1; i+=2){
printf("%d %d 1\n",a[b2-1+i],a[b2+i]);
d=max(d,b2+i);
}
for(int i=d+1; ; i++)
if(a[i]!=id&&a[i]!=2){
printf("%d %d 1\n",1,a[i]);break;
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: