|
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:
", TT);
for (int i = 0; i < n; i ++) printf("%d", S[i]);
puts ("");
}
return 0;
}