---
title: Bridges Painting
tags:
  - Constructive Algorithm
  - Depth-First-Search
id: "1560"
categories:
  - [OI, Common Skill]
  - [OI, Graph Theory]
date: 2017-10-19 19:45:43
---

## 题目描述

New Berland consists of $N$ islands, some of them are connected by bridges. There can be no more than one bridge between any pair of islands. Mr. President issued a law to paint all bridges. A bridge can be painted white or black. Any island must have at least one white bridge and at least one black (of course if an island has more than one bridge).

## 题意概述

给定一张图，要求将所有边染成黑白两种颜色，使得每个度数大于$1$的点的连边都至少有一条黑色和一条白色。

数据范围：$1 \le N \le 100$。

## 算法分析

显然，我们可以分别考虑每个连通块。如果某个连通块仅由一个奇环构成，则不存在合法方案；否则，在连通块内任选一个度数不为$2$的点，从它开始进行交错染色（DFS）；如果所有点的度数均为$2$，则任选一个点开始进行交错染色，再检验合法性。证明如下：

> 考虑 DFS 的过程。如果 DFS 经过一个点（进入并出去），根据交错染色的原则，入边和出边的颜色一定不相同。对于连通块内某个度数为$1$的点，它的连边可以任意染色；而对于度数大于$2$的点，如果从它开始 DFS，则一定会再经过这个点至少一次。

由此得证。

## 代码

```cpp
#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

struct IOManager {
  template <typename T> inline bool read(T &x) { char c = '\n'; bool flag = false; x = 0; while (~ c && ! isdigit(c = getchar()) && c != '-') ; c == '-' && (flag = true, c = getchar()); if (! ~ c) return false; while (isdigit(c)) x = (x << 3) + (x << 1) + c - '0', c = getchar(); return (flag && (x = -x), true); }
  inline bool read(char &c) { c = '\n'; while (~ c && ! (isprint(c = getchar()) && c != ' ')) ; return ~ c; }
  inline int read(char s[]) { char c = '\n'; int len = 0; while (~ c && ! (isprint(c = getchar()) && c != ' ')) ; if (! ~ c) return 0; while (isprint(c) && c != ' ') s[len ++] = c, c = getchar(); return (s[len] = '\0', len); }
  template <typename T> inline IOManager operator > (T &x) { read(x); return *this; }
  template <typename T> inline void write(T x) { if (x < 0) putchar('-'), x = -x; if (x > 9) write(x / 10); putchar(x % 10 + '0'); }
  inline void write(char c) { putchar(c); }
  inline void write(char s[]) { int pos = 0; while (s[pos] != '\0') putchar(s[pos ++]); }
  template <typename T> inline IOManager operator < (T x) { write(x); return *this; }
} io;

struct Solver {
private:
  static const int N = 110;
  int n, col[N][N];
  vector <int> mp[N];
  void input() {
    io > n;
    for (int i = 1; i <= n; ++ i) {
      int t; io > t;
      while (t) mp[i].push_back(t), io > t;
    }
  }
  void dfs(int t, int c) {
    for (int i = 0; i < mp[t].size(); ++ i)
      if (! col[t][mp[t][i]]) col[t][mp[t][i]] = col[mp[t][i]][t] = c, dfs(mp[t][i], c = 3 - c);
  }
  void process() {
    for (int i = 1; i <= n; ++ i) if (mp[i].size() != 2) dfs(i, 1);
    for (int i = 1; i <= n; ++ i) dfs(i, 1);
    for (int i = 1; i <= n; ++ i) {
      bool w = false, b = false;
      for (int j = 0; j < mp[i].size(); ++ j) w |= col[i][mp[i][j]] == 1, b |= col[i][mp[i][j]] == 2;
      if (mp[i].size() > 1 && ! (w && b)) { io < (char *) "No solution\n"; return; }
    }
    for (int i = 1; i <= n; ++ i) {
      for (int j = 0; j < mp[i].size(); ++ j) io < col[i][mp[i][j]] < ' ';
      io < 0 < '\n';
    }
  }

public:
  void solve() { input(), process(); }
} solver;

int main() {
  solver.solve();
  return 0;
}
```
