zoukankan      html  css  js  c++  java
  • 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

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

    传送门

    > 别忘了 总有人在等着你
  • 相关阅读:
    Java 代理模式
    ReentrantLock 详解
    Java线程池详解
    ConcurrentHashMap 解读
    CountDownLatch/CyclicBarrie用法记录
    微信接入笔记记录
    iOS设计模式
    iOS设计模式
    iOS设计模式
    iOS设计模式
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9761169.html
Copyright © 2011-2022 走看看