Practice I 图论

Chapter I 强连通分量以及割点

T1 poj 3180 The Cow Prom

Time cost: 35min

比较明显的板子题

缩点记录一下分量点数

注意除去点数少于2的情况

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define rep(i,a,n) for(int i = a;i <= n;i++)
 6 #define per(i,n,a) for(int i = n;i >= a;i--)
 7 using namespace std;
 8 typedef long long ll;
 9 ll read() {
10     ll as = 0,fu = 1;
11     char c = getchar();
12     while(c < '0' || c > '9') {
13         if(c == '-') fu = -1;
14         c = getchar();
15     }
16     while(c >= '0' && c <= '9') {
17         as = as * 10 + c - '0';
18         c = getchar();
19     }
20     return as * fu;
21 }
22 const int N = 50005;
23 //head
24 int n,m,ans;
25 int mo[N],nxt[N],head[N],cnt;
26 void add(int x,int y) {
27     mo[++cnt] = y;
28     nxt[cnt] = head[x];
29     head[x] = cnt;
30 }
31 
32 int dfn[N],low[N],stk[N],sze[N],col[N];
33 int top,idx,scc;
34 bool ins[N];
35 void tarjan(int x) {
36     dfn[x] = low[x] = ++idx;
37     stk[++top] = x,ins[x] = 1;
38     for(int i = head[x];i;i = nxt[i]) {
39     int sn = mo[i];
40     if(!dfn[sn]) {
41         tarjan(sn);
42         low[x] = min(low[x],low[sn]);
43     } else if(ins[sn]) low[x] = min(low[x],dfn[sn]);
44     }
45     if(low[x] == dfn[x]) {
46     int t = -1;
47     scc++;
48     while(t != x) {
49         t = stk[top--];
50         ins[t] = 0;
51         col[t] = scc;
52         sze[scc]++;
53     }
54     }
55 }
56 
57 
58 int main() {
59     n = read();
60     m = read();
61     rep(i,1,m) {
62     int x = read();
63     int y = read();
64     add(x,y);
65     }
66     rep(i,1,n) if(!dfn[i]) tarjan(i);
67     rep(i,1,scc) if(sze[i] >= 2) ans++;
68     printf("%d
",ans);
69     return 0;
70 }
View Code

T2 poj 1236 Network of Schools

Time cost: 45min

不再是板子

题意较为明显的拓扑意识 先缩点

对于剩下的DAG

第一问 只要所有入度为0的点放入软件就行

第二问 考虑最坏情况 选择了一个出度为0的点放软件

所以就能要保证入度为0的点都接到或者保证出度为0的点都能发出去

所以答案就是rdu[]==0和cdu[]==0的较大值

Code:(这里是luogu加强版P2812)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define ms(a,b) memset(a,b,sizeof a)
 6 #define rep(i,a,n) for(int i = a;i <= n;i++)
 7 #define per(i,n,a) for(int i = n;i >= a;i--)
 8 using namespace std;
 9 typedef long long ll;
10 ll read() {
11     ll as = 0,fu = 1;
12     char c = getchar();
13     while(c < '0' || c > '9') {
14         if(c == '-') fu = -1;
15         c = getchar();
16     }
17     while(c >= '0' && c <= '9') {
18         as = as * 10 + c - '0';
19         c = getchar();
20     }
21     return as * fu;
22 }
23 const int N = 10005;
24 //head
25 int n,m,ans1,ans2;
26 int mo[5000005],nxt[5000005],head[N],cnt;
27 void add(int x,int y) {
28     mo[++cnt] = y;
29     nxt[cnt] = head[x];
30     head[x] = cnt;
31 }
32 void clr(){ms(head,0),cnt = 0;}
33 
34 int dfn[N],low[N],stk[N],sze[N],col[N];
35 int top,idx,scc;
36 bool ins[N];
37 void tarjan(int x) {
38     dfn[x] = low[x] = ++idx;
39     stk[++top] = x,ins[x] = 1;
40     for(int i = head[x];i;i = nxt[i]) {
41     int sn = mo[i];
42     if(!dfn[sn]) {
43         tarjan(sn);
44         low[x] = min(low[x],low[sn]);
45     } else if(ins[sn])
46         low[x] = min(low[x],dfn[sn]);
47     }
48     if(low[x] == dfn[x]) {
49     int t = -1;
50     scc++;
51     while(t != x) {
52         t = stk[top--];
53         ins[t] = 0;
54         col[t] = scc;
55         sze[scc]++;
56     }
57     }
58 }
59 int str[5000005],stp[5000005];
60 int rdu[N],cdu[N];
61 
62 int main() {
63     n = read();
64     rep(x,1,n) while(1) {
65     int y = read();
66     if(!y) break;    
67     str[++m] = x,stp[m] = y;
68     add(x,y);
69     }
70     rep(i,1,n) if(!dfn[i]) tarjan(i);
71     if(scc == 1) {
72     printf("1
0
");
73     return 0;
74     }
75     clr();
76     rep(i,1,m) {
77     if(col[str[i]] == col[stp[i]]) continue;
78     add(col[str[i]],col[stp[i]]);
79     cdu[col[str[i]]]++,rdu[col[stp[i]]]++;
80     }
81     rep(i,1,scc) {
82     if(!rdu[i]) ans1++;
83     if(!cdu[i]) ans2++;
84     }
85     printf("%d
%d
",ans1,max(ans1,ans2));
86 }
View Code

Chapter II 图的割点、桥与双连通分量

T1 poj3177 Redundant Paths

Time cost:55min

例题还是说一下(边双做的比较少……)

求加最少的边使得整个图为一边双

先找出所有的桥/边双 然后缩点

发现变成一个点数为边双个数的树

考虑树上的一条链 加一条边就是一个边双

所以最后加边的个数就是(叶节点个数+1)/2

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define ms(a,b) memset(a,b,sizeof a)
 6 #define rep(i,a,n) for(int i = a;i <= n;i++)
 7 #define per(i,n,a) for(int i = n;i >= a;i--)
 8 using namespace std;
 9 typedef long long ll;
10 ll read() {
11     ll as = 0,fu = 1;
12     char c = getchar();
13     while(c < '0' || c > '9') {
14     if(c == '-') fu = -1;
15     c = getchar();
16     }
17     while(c >= '0' && c <= '9') {
18     as = as * 10 + c - '0';
19     c = getchar();
20     }
21     return as * fu;
22 }
23 const int N = 20005;
24 //head
25 int n,m,ans;
26 int head[N],nxt[N],fo[N],mo[N],cnt = 1;
27 bool cut[N];
28 void _add(int x,int y) {
29     fo[++cnt] = x;
30     mo[cnt] = y;
31     nxt[cnt] = head[x];
32     head[x] = cnt;
33 }
34 void add(int x,int y){if(x^y)_add(x,y),_add(y,x);}
35 
36 int dfn[N],low[N],stk[N],col[N];
37 int top,idx,scc;
38 bool ins[N];
39 void tarjan(int x,int f) {
40     dfn[x] = low[x] = ++idx;
41     stk[++top] = x,ins[x] = 1;
42     bool flag = 0;
43     for(int i = head[x];i;i = nxt[i]) {
44     int sn = mo[i];
45     if(sn == f && !flag) {
46         flag = 1;
47         continue;
48     }
49     if(!dfn[sn]) {
50         tarjan(sn,x);
51         low[x] = min(low[x],low[sn]);
52     } else if(ins[sn]) low[x] = min(low[x],dfn[sn]);
53     }
54     if(low[x] == dfn[x]) {
55     int t = -1;
56     scc++;
57     while(t!=x) {
58         t = stk[top--];
59         col[t] = scc;
60         ins[t] = 0;
61     }
62     }
63 }
64 int du[N];
65 int main() {
66     n = read();
67     m = read();
68     rep(i,1,m) {
69     int x = read();
70     int y = read();
71     add(x,y);
72     }
73     rep(i,1,n) if(!dfn[i]) tarjan(i,i);
74     rep(x,1,n) {
75     for(int i = head[x];i;i = nxt[i]) {
76         int sn = mo[i];
77         if(col[x] ^ col[sn]) du[col[x]]++,du[col[sn]]++;
78     }
79     }
80     rep(i,1,scc) if(du[i] == 2) ans++;
81     printf("%d
",ans+1 >> 1);
82     return 0;
83 }
View Code

T2 poj 1523 SPF

Time cost: 60min

不敢说是板……因为输入输出贼恶心

每个方案之间还要换行……

然后WA了一次是因为考虑根节点为割点的时候多算了1

整体的思路就是求出割点弹栈的时候记录一下这个点“做了几次割点”

实现的时候就是cut[x] =1变成cut[x]++就Ok

Code:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cmath>
  5 #define ms(a,b) memset(a,b,sizeof a)
  6 #define rep(i,a,n) for(int i = a;i <= n;i++)
  7 #define per(i,n,a) for(int i = n;i >= a;i--)
  8 using namespace std;
  9 typedef long long ll;
 10 ll read() {
 11     ll as = 0,fu = 1;
 12     char c = getchar();
 13     while(c < '0' || c > '9') {
 14     if(c == '-') fu = -1;
 15     c = getchar();
 16     }
 17     while(c >= '0' && c <= '9') {
 18     as = as * 10 + c - '0';
 19     c = getchar();
 20     }
 21     return as * fu;
 22 }
 23 const int N = 20005;
 24 //head
 25 int minn,maxx;
 26 int head[N],mo[N],nxt[N],cnt;
 27 void _add(int x,int y) {
 28     mo[++cnt] = y;
 29     nxt[cnt] = head[x];
 30     head[x] = cnt;
 31 }
 32 void add(int x,int y) {if(x^y)_add(x,y),_add(y,x);}
 33 
 34 int dfn[N],low[N],col[N],sze[N],stk[N];
 35 int top,scc,idx;
 36 int cut[N];
 37 void tarjan(int x,bool rt) {
 38     dfn[x] = low[x] = ++idx;
 39     stk[++top] = x;
 40     for(int i = head[x];i;i = nxt[i]) {
 41     int sn = mo[i];
 42     if(!dfn[sn]) {
 43         tarjan(sn,0);
 44         low[x] = min(low[x],low[sn]);
 45         if(low[sn] == dfn[x]) {
 46         int t = -1;
 47         sze[++scc]++;
 48         while(t != sn) {
 49             t = stk[top--];
 50             sze[scc]++;
 51             col[t] = scc;
 52         }
 53         cut[x]++;
 54         }
 55     } else low[x] = min(low[x],dfn[sn]);
 56     }
 57     if(rt) cut[x]--;
 58 }
 59 
 60 void solve() {
 61     tarjan(minn,1);
 62     bool flag = 0;
 63     rep(i,minn,maxx) if(cut[i]) {
 64     flag = 1;
 65     printf("  SPF node %d leaves %d subnets
",i,cut[i] + 1);
 66     }
 67     if(!flag) puts("  No SPF nodes");
 68 }
 69 
 70 void clr() {
 71     ms(head,0);
 72     ms(dfn,0),ms(low,0),ms(cut,0);
 73     top = cnt = idx = scc = 0;
 74 }
 75 
 76 int main() {
 77     int T = 0;
 78     while(1) {
 79     int x,y;
 80     clr();
 81     x = read();
 82     if(!x) break;
 83     y = read();
 84     add(x,y);
 85     minn = min(x,y);
 86     maxx = max(x,y);
 87     while(1) {
 88         x = read();
 89         if(!x) break;
 90         y = read();
 91         add(x,y);
 92         minn = min(min(x,y),minn);
 93         maxx = max(max(x,y),maxx);
 94     }
 95     printf("Network #%d
",++T);
 96     solve();
 97     puts("");
 98     }
 99     return 0;
100 }
View Code

T3 poj 2942 Knights of the Round Table

Time cost : 85min

Tarjan快结束了就出一个建图及其恶心的题……

给你的憎恨关系要先转成友好关系(想到这过去了30min)

然后求奇数大小点双的个数  => 二分图染色!

发现下一个点已经有相同的颜色了就返回true

注意:

1.相反颜色继续向后找其他边而不是return 0

2.割点在每个点双里面都要重新染色 (然后就需要vector存点...)

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<queue>
 6 #define ms(a,b) memset(a,b,sizeof a)
 7 #define rep(i,a,n) for(int i = a;i <= n;i++)
 8 #define per(i,n,a) for(int i = n;i >= a;i--)
 9 #define inf 2147483647
10 using namespace std;
11 typedef long long ll;
12 ll read() {
13     ll as = 0,fu = 1;
14     char c = getchar();
15     while(c < '0' || c > '9') {
16         if(c == '-') fu = -1;
17         c = getchar();
18     }
19     while(c >= '0' && c <= '9') {
20         as = as * 10 + c - '0';
21         c = getchar();
22     }
23     return as * fu;
24 }
25 const int N = 1005;
26 //head
27 int n,m;
28 int v[N][N];
29 
30 int dfn[N],low[N],stk[N],col[N];
31 int scc,idx,top;
32 vector<int> mem[N];
33 void tarjan(int x,int f) {
34     dfn[x] = low[x] = ++idx;
35     stk[++top] = x;
36     rep(y,1,n) {
37         if(!v[x][y] || x == y) continue;
38         if(!dfn[y]) {
39             tarjan(y,x);
40             low[x] = min(low[x],low[y]);
41             if(low[y] == dfn[x]) {
42                 int t = -1;
43                 mem[++scc].push_back(x);
44                 while(t != y) {
45                     t = stk[top--];
46                     mem[scc].push_back(t);
47                 }
48             }
49         } else low[x] = min(low[x],dfn[y]);
50     }
51 }
52 
53 int mrk[N];
54 bool paint(int x,bool d) {
55     mrk[x] = d;
56     rep(y,1,n) {
57         if(!v[x][y] || x == y) continue;
58         if(col[x] ^ col[y]) continue;
59         if(mrk[y] == mrk[x]) return 1;
60         else if(mrk[y] == -1 && paint(y,d^1)) return 1;
61     }
62     return 0;
63 }
64 int ans[N];
65 void clr() {
66     rep(i,0,n+1) rep(j,0,n+1) v[i][j] = true;
67     rep(i,1,scc) mem[i].clear();
68     idx = scc = top = 0;
69     ms(dfn,0),ms(low,0),ms(col,0),ms(ans,0);
70 }
71 
72 int main() { 
73     while(1) {
74         n = read(),m = read();
75         if(!n && !m) return 0;
76         clr();
77         rep(i,1,m) {
78             int x = read(),y = read();
79             v[y][x] = v[x][y] = 0;
80         }
81         rep(i,1,n) if(!dfn[i]) tarjan(i,i);
82         rep(i,1,scc) {
83             ms(mrk,-1);
84             int sze = (int)mem[i].size();
85             rep(j,0,sze-1) col[mem[i][j]] = i;
86             if(paint(mem[i][0],0)) {
87                 rep(j,0,sze - 1) ans[mem[i][j]] = 1;
88             }
89         }
90         int res = 0;
91         rep(i,1,n) res += !ans[i];
92         printf("%d
",res);
93     }
94 }
View Code

Chapter III 2-SAT

讲解传送门

T1 poj 3678 Katu Puzzle

Time cost: 45min

2-SAT中能遇到的比较常见的限制都在这道题里了

分析一下

1.xΛy == 1 x,y都不为0 连边x->x+n , y->y+n

2.xΛy == 0 <=> ~xV~y == 1 <=> 连边x->y+n , y->x+n

3.xVy == 1 连边x+n->y , y+n -> x

4.xVy == 0 x,y都为0 连边

这里注意一下 就是异或是能由一个直接确定另一个的 所以需要加四条边

当然也可以考虑成满足或 不满足与(就不写了 代码里有)

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define itn int
 6 #define ms(a,b) memset(a,b,sizeof a)
 7 #define rep(i,a,n) for(int i = a;i <= n;i++)
 8 #define per(i,n,a) for(int i = n;i >= a;i--)
 9 using namespace std;
10 typedef long long ll;
11 ll read() {
12     ll as = 0,fu = 1;
13     char c = getchar();
14     while(c < '0' || c > '9') {
15         if(c == '-') fu = -1;
16         c = getchar();
17     }
18     while(c >= '0' && c <= '9') {
19         as = as * 10 + c - '0';
20         c = getchar();
21     }
22     return as * fu;
23 }
24 const int N = 3005;
25 //head
26 int n,m;
27 int head[N],nxt[N*N],mo[N*N],cnt;
28 void add(itn x,int y) {
29     mo[++cnt] = y;
30     nxt[cnt] = head[x];
31     head[x] = cnt;
32 }
33 
34 int dfn[N],low[N],stk[N],col[N];
35 int top,scc,idx;
36 bool ins[N];
37 void tarjan(itn x) {
38     dfn[x] = low[x] = ++idx;
39     stk[++top] = x,ins[x] = 1;
40     for(int i = head[x];i;i = nxt[i]) {
41     int sn = mo[i];
42     if(!dfn[sn]) {
43         tarjan(sn);
44         low[x] = min(low[x],low[sn]);
45     } else if(ins[sn]) low[x] = min(low[x],dfn[sn]);
46     }
47     if(low[x] == dfn[x]) {
48     int t = -1;
49     scc++;
50     while(t!=x) {
51         t = stk[top--];
52         ins[t] = 0;
53         col[t] = scc;
54     }
55     }
56 }
57 char s[7];
58 int main() {
59     n = read();
60     m = read();
61     rep(i,1,m) {
62     int x = read() + 1;
63     int y = read() + 1;
64     bool op = read();
65     scanf("%s",s);
66     if(s[0] == 'A') {
67         if(op) add(x+n,x),add(y+n,y);
68         else add(x,y+n),add(y,x+n);
69     } else if(s[0] == 'O') {
70         if(op) add(x+n,y),add(y+n,x);
71         else add(x,x+n),add(y,y+n);
72     } else if(s[0] == 'X'){
73         if(op) add(x+n,y),add(y+n,x),add(x,y+n),add(y,x+n);
74         else add(x,y),add(y,x),add(x+n,y+n),add(y+n,x+n);
75     }
76     }
77     rep(i,1,n<<1) if(!dfn[i]) tarjan(i);
78     bool flag = 1;
79     rep(i,1,n) if(col[i] == col[n+i]) flag = 0;
80     flag ? puts("YES") : puts("NO");
81     return 0;
82 }
View Code

T2 luogu  P4171 [JSOI2010]满汉全席

Time cost:45min

2-SAT基础  每一对关系都是|| 逆向连边即可

(luogu读入依然坑人……)

Code:

 1 // luogu-judger-enable-o2
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<queue>
 7 #define ms(a,b) memset(a,b,sizeof a)
 8 #define rep(i,a,n) for(int i = a;i <= n;i++)
 9 #define per(i,n,a) for(int i = n;i >= a;i--)
10 #define inf 2147483647
11 using namespace std;
12 typedef long long ll;
13 ll read() {
14     ll as = 0,fu = 1;
15     char c = getchar();
16     while(c < '0' || c > '9') {
17         if(c == '-') fu = -1;
18         c = getchar();
19     }
20     while(c >= '0' && c <= '9') {
21         as = as * 10 + c - '0';
22         c = getchar();
23     }
24     return as * fu;
25 }
26 const int N = 4005;
27 //head
28 int n,m;
29 int head[N],nxt[N],mo[N],cnt;
30 void add(int x,int y) {
31     mo[++cnt] = y;
32     nxt[cnt] = head[x];
33     head[x] = cnt; 
34 }
35 
36 int dfn[N],low[N],stk[N],col[N];
37 int scc,idx,top;
38 bool ins[N];
39 void tarjan(int x) {
40     dfn[x] = low[x] = ++idx;
41     stk[++top] = x,ins[x] = 1;
42     for(int i = head[x];i;i = nxt[i]) {
43         int sn = mo[i];
44         if(!dfn[sn]) {
45             tarjan(sn);
46             low[x] = min(low[x],low[sn]);
47         } else if(ins[sn])
48             low[x] = min(low[x],dfn[sn]);
49     }
50     if(dfn[x] == low[x]) {
51         int t = -1;
52         scc++;
53         while(t != x) {
54             t = stk[top--];
55             col[t] = scc;
56             ins[t] = 0;
57         }
58     }
59 }
60 
61 int rev(int x){return x>n?x-n:x+n;}
62 void clr() {
63     n = m = 0;
64     ms(head,0),ms(dfn,0),ms(low,0),ms(col,0);
65     scc = cnt = idx = 0;
66 }
67 
68 void solve() {
69     clr();
70     n = read();
71     m = read();
72     rep(i,1,m) {
73         int x,y;
74         rep(t,0,1) {
75             int num = 0;
76             char s[10];
77             scanf("%s",s);
78             int l = strlen(s);
79             rep(j,1,l-1) num = num * 10 + s[j] - '0';
80             if(s[0] == 'h') num += n;
81             t ? y = num : x = num;
82         }
83         add(rev(x),y),add(rev(y),x);
84     }
85     rep(i,1,n<<1) if(!dfn[i]) tarjan(i);
86     bool flag = 1;
87     rep(i,1,n) if(col[i] == col[n+i]) {
88         flag = 0;
89         break;
90     }
91     flag ? puts("GOOD") : puts("BAD");
92 }
93 
94 int main() {
95     int T = read();
96     while(T--) solve();
97     return 0;
98 }
View Code

T3 poj3177 Wedding

Time cost:100min

最后输出出锅调一个点……

题意就是比较明显的2-SAT

但是这个题已经拆好点了

我们把新郎一边为0新郎一边为1 那么每对关系就是||

最后要新郎到新娘连一条边表示求的是与新郎坐在一起的人

大力建图就OK

最后输出的时候注意空格的问题……

还有读入的时候忘了数字可以有多位就一直RE……

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #define itn int
 6 #define ms(a,b) memset(a,b,sizeof a)
 7 #define rep(i,a,n) for(int i = a;i <= n;i++)
 8 #define per(i,n,a) for(int i = n;i >= a;i--)
 9 using namespace std;
10 typedef long long ll;
11 ll read() {
12     ll as = 0,fu = 1;
13     char c = getchar();
14     while(c < '0' || c > '9') {
15         if(c == '-') fu = -1;
16         c = getchar();
17     }
18     while(c >= '0' && c <= '9') {
19         as = as * 10 + c - '0';
20         c = getchar();
21     }
22     return as * fu;
23 }
24 const int N = 2005;
25 //head
26 int n,m;
27 int head[N],nxt[400005],mo[400005],cnt;
28 void add(int x,int y) {
29     mo[++cnt] = y;
30     nxt[cnt] = head[x];
31     head[x] = cnt;
32 }
33 int dfn[N],low[N],stk[N],col[N];
34 int top,idx,scc;
35 bool ins[N];
36 void tarjan(int x) {
37     dfn[x] = low[x] = ++idx;
38     stk[++top] = x,ins[x] = 1;
39     for(int i = head[x];i;i = nxt[i]) {
40     int sn = mo[i];
41     if(!dfn[sn]) {
42         tarjan(sn);
43         low[x] = min(low[x],low[sn]);
44     } else if(ins[sn])
45         low[x] = min(low[x],dfn[sn]);
46     }
47     if(low[x] == dfn[x]) {
48     int t = -1;
49     ++scc;
50     while(t != x) {
51         t = stk[top--];
52         ins[t] = 0;
53         col[t] = scc;
54     }
55     }
56 }
57 int rev(int x){return x>n?x-n:x+n;}
58 void clr() {
59     ms(head,0),ms(dfn,0),ms(low,0),ms(col,0);
60     idx = scc = cnt = 0;
61 }
62 
63 int main() {
64     while(1) {
65     n = read();
66     m = read();
67     if(!n && !m) return 0;
68     clr();
69     rep(i,1,m) {
70         int x,y;
71         char c1,c2;
72         scanf("%d%c %d%c",&x,&c1,&y,&c2);
73         x = x + 1 + (c1 == 'h') * n;
74         y = y + 1 + (c2 == 'h') * n;
75         add(x,rev(y)),add(y,rev(x));
76     }
77     add(1,n+1);
78     rep(i,1,n<<1) if(!dfn[i]) tarjan(i);
79     bool flag = 1;
80     rep(i,1,n) if(col[i] == col[n+i]) flag = 0;
81     if(!flag) {
82         puts("bad luck");
83         continue;
84     }
85     rep(i,2,n) 
86         printf("%d%c ",i-1,col[i] > col[i+n] ? 'w' : 'h');
87     puts("");
88     }
89 }
View Code

Chapter IV Euleriar path

没找到什么经典题啊…… 就整一下概念吧

传送门

> 别忘了 总有人在等着你
原文地址:https://www.cnblogs.com/yuyanjiaB/p/9761169.html