2014百度之星初赛第一轮解题报告:CycleCocycle
CycleCocycle
时间限制:10s 内存限制:64MB
问题描述
有一个n个点m条边的图,你要给每个点一个0或1的标号,使得每个点与偶数个相同标号的点之间有边。如果有多解输出任意一组。
输入
第一行为T,表示输入数据组数。
下面T组数据。每组数据中:
第一行,n,m。
下面m行,每行两个数x,y,表示一条边。
输出
对第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; }