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;

}

  

你可能感兴趣的:(HDU)