hdu5302 构造

题意:

一个无向图,每条边要么是白色要么是黑色

每个点最多与2条白边相连,每个点最多与两条黑边相连

现在告诉你w0, w1, w2和b0, b1, b2

表示有wi个点周围有i条白边, 有bi个点周围有i条黑边

现在要求构造这个图,没有自环重边,且满足wi, bi的要求,输出每条边以及颜色

 

思路:

n<=4可以手动构造

对于n>4, 我们首先可以在n个点上构造一个白环,一个黑环,每个环都包括所有点,并且没有重边

对于奇数n:

  白环 1 2 3 ... n

  黑环 1 3 5 ... n 2 4 6 ... n-1

对于偶数n:

  白环 1 2 3 ... n

  黑环 1 3 5 ... n-1 2 n n-2 n-4 ... 4

 

最后的答案肯定是这个双环的子图

白色和黑色是独立的,可以分开考虑

例如白边,把所有2°点排成一排,在两端各放一个1°点,剩下来的1°点两两配对,0°点不考虑

只要1°点是偶数就有解

 

#include <cstdio>
#include <vector>
using namespace std;
const int N = 6000;
int n, total;
int w[3], b[3];
int L[N+5], R[N+5];
vector<int> f[N+5], g[N+5];
inline void con(vector<int> ch[], int a, int b){
    ++total;
    if (a<b) ch[a].push_back(b);
    else ch[b].push_back(a);
}
inline void go(int c[], vector<int> ch[]){
    int st = 1, ed;
    for (int i=1, u=1; i<=c[2]; i++, u=R[u]){
        if (i == c[2]){
            ed = u;
        } else{
            con(ch, u, R[u]);
        }
    }
    con(ch, L[st], st);
    con(ch, ed, R[ed]);
    for (int i=1, u=R[R[ed]]; i<=c[1]-2; i+=2, u=R[R[u]]){
        con(ch, u, R[u]);
    }
}
void output(){
    printf("%d\n", total);
    for (int i=1; i<=n; i++){
        for (int j=0; j<f[i].size(); j++){
            printf("%d %d 0\n", i, f[i][j]);
        }
        for (int j=0; j<g[i].size(); j++){
            printf("%d %d 1\n", i, g[i][j]);
        }
    }
}
int main(){
//freopen("1003.in", "r", stdin);
//freopen("1003.txt", "w", stdout);
    int test;
    scanf("%d", &test);
    for (int T=1; T<=test; T++){
        n = total = 0;
        for (int i=0; i<3; i++) scanf("%d", &w[i]);
        for (int i=0; i<3; i++) scanf("%d", &b[i]);
        for (int i=0; i<3; i++) n += w[i];
        for (int i=1; i<=n; i++){
            f[i].clear();
            g[i].clear();
        }
        if ((w[1]&1) || (b[1]&1)){
            puts("-1");
            continue;
        }
        if (n==4){
            con(f, 1, 2);
            con(f, 1, 3);
            con(g, 4, 2);
            con(g, 4, 3);
            output();
            continue;
        }
        for (int i=1; i<=n; i++){
            L[i] = i-1;
            R[i] = i+1;
        }
        L[1] = n;
        R[n] = 1;
        go(w, f);
        if (n&1){
            for (int i=1; i<=n; i++){
                L[i] = i-2;
                R[i] = i+2;
            }
            L[1] = n-1;
            R[n-1] = 1;
            L[2] = n;
            R[n] = 2;
        } else{
            for (int i=1; i<=n; i+=2){
                L[i] = i-2;
                R[i] = i+2;
            }
            for (int i=2; i<=n; i+=2){
                L[i] = i+2;
                R[i] = i-2;
            }
            L[1] = 4;
            R[4] = 1;
            L[2] = n-1;
            R[2] = n;
            L[n] = 2;
            R[n-1] = 2;
        }
        go(b, g);
        output();
    }
    return 0;
}

  

posted @ 2015-07-25 14:35  ALPC_Flagship  阅读(283)  评论(0编辑  收藏  举报