油漆门
有一些无向边,要求给每条边的两端点染成黄色和绿色且两端点染成的颜色不同,使得连向每一个房间绿端点的数量与黄端点的数量之差不超过1。没有重边。1<=n<=100。
做法1
我们可以把图中的所有环删掉,容易知道答案不变。
接下来图就变成了一个森林,对于一棵树,我们只要把孩向边间隔染色,第一条边染的颜色与父向边染的颜色不同,就可以满足条件。
做法2
我们把每两个奇度数的点之间连边,接下来图中就只剩下若干个环了,就可以直接暴搜了。
感觉第二种做法特别神啊!
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <vector> using namespace std; int n,he[233][233],M=0; int col[233][233]; typedef vector<int> vec; vec vs[2333]; char yy[2333]; void dfs(int x) { for(int i=1;i<=n;i++) { while(he[x][i]) { --he[x][i]; --he[i][x]; dfs(i); col[x][i]=1; col[i][x]=0; } } } #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);} int main() { FO(painting) yy[1]='G'; yy[0]='Y'; scanf("%d",&n); int lst=0; for(int i=1;i<=n;i++) { int x,y; scanf("%d",&x); if(x&1) { if(!lst) lst=i; else he[i][lst]++, he[lst][i]++, lst=0; } while(x--) { scanf("%d",&y); vs[i].push_back(y); he[i][y]++; } } for(int i=1;i<=n;i++) dfs(i); for(int i=1;i<=n;i++) { for(int j=0;j<vs[i].size();j++) { int c=vs[i][j]; putchar(yy[col[i][c]]); putchar(' '); } putchar(10); } }