题目大意:有个一无向图,给所有的边染色,如果一个点连接的边超过两个,那么最少要染一个白色和一个黑色,能否给整个图染色?不能输出“No solution”。
分析:引用连接 http://edward-mj.com/archives/445
首先构建dfs树,无向图dfs树具有的一大优点是该点只会向自己的祖先或子孙有非树边。
然后按深度交替染色。返祖边与自己的儿子涂同样的颜色。
如果dfs树中根结点度超过1,那么就找一条边染不同的颜色。
否则看根结点是否满足条件,如果不是,那么找一个与根结点相连的叶子,向上找到一个度大于2的点为止,将该路径上所以边反色,并且将根与该叶子的边反色。如果找不到度大于2的点,那么是奇环,无解。
ps.注意这组数据:
5
2 3 0
1 3 0
1 2 4 5 0
3 5 0
3 4 0
代码如下:
======================================================================================================================
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> using namespace std; const int MAXN = 107; int c[MAXN][MAXN], N;///保存边的颜色, N个点 int father[MAXN], nSon[MAXN]; vector<int> e[MAXN];///相连接的点 void DFS(int u, int color) { for(int i=0; i<e[u].size(); i++) { if(c[u][e[u][i]] != -1) continue;///这条边已经被访问过 nSon[u]++;///子树数目加1 c[e[u][i]][u] = c[u][e[u][i]] = color; if(!nSon[e[u][i]]) {///如果不是连接的祖边 father[e[u][i]] = u; DFS(e[u][i], color^1); } } } int main() { int i, j, x; scanf("%d", &N); for(i=1; i<=N; i++) { while(scanf("%d", &x), x) e[i].push_back(x); } memset(c, -1, sizeof(c)); for(i=1; i<=N; i++) { if(nSon[i] || father[i] || e[i].size()==0) continue; ///没有父节点,也没有儿子节点,说明未被访问过 for(j=0; j<e[i].size(); j++) {///与根节点连接的第一个节点赋值为颜色0,后面的赋值为别的颜色 if(j==0) { nSon[i]++, father[e[i][j]] = i; c[i][e[i][j]] = c[e[i][j]][i] = 0; DFS(e[i][j], 1); } else if(c[i][e[i][j]] == -1) {///这条边未被访问过 nSon[i]++, father[e[i][j]] = i; c[i][e[i][j]] = c[e[i][j]][i] = 1; DFS(e[i][j], 0); } } if(nSon[i] >= 2 || e[i].size() == 1) continue; ///如果根节点的子树数目小于2,或者只有一个子节点 for(j=1; j<e[i].size(); j++) {///从子节点往父节点查找一个节点有大于或等于两个子树的节点 ///如果找到那么就把这条路径上的所有边取反,如果找不到,无解 x = e[i][j]; if(c[x][i] == 1) break;///不需要取反也可以 while(father[x] != i && nSon[x] < 2) x = father[x]; if(father[x] == i) continue;///未找到这样的节点 x = e[i][j]; c[x][i] = c[i][x] = 1; while(nSon[x] < 2) {///路径上的边取反 c[x][father[x]] = c[father[x]][x] = c[x][father[x]] ^ 1; x = father[x]; } break; } if(j == e[i].size()) break;///无解 } if(i <= N) printf("No solution\n"); else { for(i=1; i<=N; i++) { for(j=0; j<e[i].size(); j++) printf("%d ", c[i][e[i][j]]+1); printf("0\n"); } } return 0; } /** 5 2 3 0 1 3 0 1 2 4 5 0 3 5 0 3 4 0 **/
Bridges painting - SGU 121(构造)
原文:http://www.cnblogs.com/liuxin13/p/4834535.html