2014百度之星初赛第一轮解题报告:CycleCocycle

CycleCocycle
时间限制:10s  内存限制:64MB
问题描述
有一个n个点m条边的图,你要给每个点一个01的标号,使得每个点与偶数个相同标号的点之间有边。如果有多解输出任意一组。
输入
第一行为T,表示输入数据组数。
下面T组数据。每组数据中:
第一行,nm
下面m行,每行两个数xy,表示一条边。
输出
对第i组数据,输出
Case #i:
然后输出一个长度为n的字符串,表示每个点的标号。
限制条件
1<=T<=100
1<=n<=1000
1<=m<=10000
1<=x, y<=n
图中无重边无自环。
样例输入
1
4 5
1 2
1 3
1 4
2 3
2 4
样例输出
Case #1:
0001

解题报告:
建立0/1线性方程组,然后解方程就可以了。每个点对应一个等式。时间复杂度O(n^3)

解题代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cassert>
#include <ctime>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <bitset>
#include <sstream>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef pair<int,int> PII;

#define fi first
#define se second
#define mp make_pair
#define pb push_back

#define N 1010

int TT, NN;
int n, m, S[N]; 
bitset<N> a[N]; 

int main () {
        scanf("%d", &NN); 
        for (TT = 1; TT <= NN; TT++) {
                scanf("%d%d", &n, &m); 
                for (int i = 0; i < n; i ++) 
                        a[i].reset(); 
                for (int i = 0; i < m; i ++) {
                        int x, y; 
                        scanf("%d%d", &x, &y); 
                        --x; --y; 
                        a[x].set(y); a[y].set(x); 
                }
                for (int i = 0; i < n; i++) 
                        if (a[i].count() & 1) {
                                a[i].set(i); 
                                a[i].set(N-1); 
                        }
                int rk = 0; 
                for (int i = 0; i < n; i ++) {
                        for (int j = rk; j < n; j ++) 
                                if (a[j][i]) {
                                        swap(a[j], a[rk]); 
                                        break; 
                                }
                        if (!a[rk][i]) continue; 
                        for (int j = rk+1; j < n; j ++) 
                                if (a[j][i]) a[j] ^= a[rk]; 
                        rk ++; 
                }
                memset(S, 0, sizeof S); 
                for (int i = rk-1; i >= 0; i --) {
                        int w = 0; 
                        while (!a[i][w]) w ++; 
                        if (a[i][N-1]) {
                                S[w] = 1; 
                                for (int j = i-1; j >= 0; j -- ) 
                                        if (a[j][w]) {
                                                a[j][w] = 0; 
                                                a[j].flip(N-1); 
                                        }
                        }
                        w --; 
                }
        printf("Case #%d:\n", TT);
                for (int i = 0; i < n; i ++) printf("%d", S[i]); 
                puts (""); 
        }
        return 0; 
}



posted @ 2014-05-27 22:02  HoseaLeo  阅读(336)  评论(1编辑  收藏  举报