zoukankan      html  css  js  c++  java
  • HDU-3472(混合图判断欧拉路 + ISAP)

    题目大意:给出n个单词,其中一些单词翻转后还是单词。求是否能首尾相接连成一条链。

    将每个单词的首尾字母作为端点,如果这个单词可以翻转,就看作一条双向边。否则,就看作一条单向边。

    用最大流处理混合图(既有双向边又有单向边)欧拉回路的时候,先忽略初始图中的有向边。为无向边指定一个方向并保留。

    然后建立一个源点s,把s连向所有度数>0的边,容量是度数/2。

    建立一个汇点t,把所有度数<0的边连向t,容量是度数/2。

    所有没连接到s或t的边,容量都为1。

    如果从s出发的所有边都满流,则存在欧拉回路。在本题中,不一定要求得欧拉回路,欧拉路也可以。

    如果图中没有度数为奇数的点,那么直接判断欧拉回路。如果图中恰有两个度数为奇数的点,在这两点之间连接一条容量为1的边,再判断欧拉回路。

    (记得判断图的联通性)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<queue>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<set>
      7 
      8 #define cl(a, n) memset(a, n, sizeof(a))
      9 #define cpy(a, b) memcpy(a, b, sizeof(b))
     10 
     11 using namespace std;
     12 typedef long long ll;
     13 const int maxn = 1e5 + 5;
     14 const int maxm = 4e5 + 5;
     15 const int INF = 0x3f3f3f3f;
     16 
     17 struct Edge{
     18     int to, Next, cap, flow, c;
     19 }edge[maxm];
     20 
     21 int tot;
     22 int head[maxn];
     23 int gap[maxn], dep[maxn], cur[maxn]; 
     24 
     25 int in[maxn], out[maxn];
     26 int vis[maxn];
     27 
     28 int f[maxn];
     29 
     30 void init(){
     31     tot = 0;
     32     cl(head, -1);
     33     cl(in, 0);
     34     cl(out, 0);
     35     cl(vis, 0);
     36     cl(f, 0);
     37 }
     38 
     39 void add(int u, int v, ll w){
     40     edge[tot].to = v; edge[tot].cap = w; edge[tot].Next = head[u];
     41     edge[tot].flow = 0; head[u] = tot++;
     42     edge[tot].to = u; edge[tot].cap = 0; edge[tot].Next = head[v];
     43     edge[tot].flow = 0; head[v] = tot++;
     44 }
     45 
     46 int Q[maxn];
     47 void bfs(int st, int ed){
     48     memset(dep, -1, sizeof(dep));
     49     memset(gap, 0, sizeof(gap));
     50     gap[0] = 1;
     51     int front = 0, rear = 0;
     52     dep[ed] = 0;
     53     Q[rear++] = ed;
     54     while(front != rear){
     55         int u = Q[front++];
     56         for(int i = head[u]; i != -1; i = edge[i].Next){
     57             int v = edge[i].to;
     58             if(dep[v] != -1) continue;
     59             Q[rear++] = v;
     60             dep[v] = dep[u] + 1;
     61             gap[dep[v]]++;
     62         }
     63     }
     64 }
     65 
     66 int S[maxn];
     67 int sap(int st, int ed, int N){
     68     bfs(st, ed);
     69     memcpy(cur, head, sizeof(head));
     70     int top = 0;
     71     int u = st;
     72     int ans = 0;
     73     while(dep[st] < N){
     74         if(u == ed){
     75             int Min = INF;
     76             int inser;
     77             for(int i = 0; i < top; i++)
     78                 if(Min > edge[S[i]].cap - edge[S[i]].flow){
     79                     Min = edge[S[i]].cap - edge[S[i]].flow;
     80                     inser = i;
     81                 }
     82                 for(int i = 0; i < top; i++){
     83                     edge[S[i]].flow += Min;
     84                     edge[S[i] ^ 1].flow -= Min;
     85                 }
     86                 ans += Min;
     87                 top = inser;
     88                 u = edge[S[top] ^ 1].to;
     89                 continue;
     90         }
     91         bool flag = false;
     92         int v;
     93         for(int i = cur[u]; i != -1; i = edge[i].Next){
     94             v = edge[i].to;
     95             if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]){
     96                 flag = true;
     97                 cur[u] = i;
     98                 break;
     99             }
    100         }
    101         if(flag){
    102             S[top++] = cur[u];
    103             u = v;
    104             continue;
    105         }
    106         int Min = N;
    107         for(int i = head[u]; i != -1; i = edge[i].Next){
    108             if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){
    109                 Min = dep[edge[i].to];
    110                 cur[u] = i;
    111             }
    112         }
    113         gap[dep[u]]--;
    114         if(!gap[dep[u]]) return ans;
    115         dep[u] = Min + 1;
    116         gap[dep[u]]++;
    117         if(u != st) u = edge[S[--top] ^ 1].to;
    118     }
    119     return ans;
    120 }
    121 
    122 
    123 int get(int x){
    124     if(x != f[x]) return f[x] = get(f[x]);
    125     else return f[x];
    126 }
    127 
    128 void Union(int x, int y){
    129     x = get(x); 
    130     y = get(y);
    131     if(x != y) f[x] = y;
    132 }
    133 
    134 int main()
    135 {
    136     int T;
    137     scanf("%d", &T);
    138     for(int K = 1; K <= T; K++){
    139         init();
    140         int n;
    141         scanf("%d", &n);
    142         for(int i = 0; i <= 26; i++) f[i] = i;
    143         int s = 0, t = 27, num = 0;
    144         for(int i = 1; i <= n; i++){
    145             char s[205];
    146             int c;
    147             scanf("%s%d", s, &c);
    148             int u = s[0] - 'a' + 1, v = s[strlen(s) - 1] - 'a' + 1;
    149             out[u]++; in[v]++;
    150             int x = get(u);
    151             int y = get(v);
    152             if(x != y) f[x] = y;
    153             if(c == 1){
    154                 add(u, v, 1);
    155             }
    156         }
    157         int cnt = 0;
    158         int odd = 0;
    159         int sum = 0;
    160         int u = 0;
    161         for(int i = 1; i <= 26; i++){
    162             if(!out[i] && !in[i]) continue;
    163             if(f[i] == i) cnt++;
    164             if(cnt > 1) break;
    165             if((out[i] - in[i])&1){
    166                 if(odd == 2) {
    167                     out[u]++; in[i]++;
    168                     add(u, i, 1);
    169                 }
    170                 u = i;
    171                 odd++;
    172             }
    173             if(out[i]-in[i] > 0) {
    174                 add(s, i, (out[i] - in[i]) / 2);
    175                 sum += (out[i] - in[i]) / 2;
    176             }
    177             else if((out[i]-in[i]) < 0) add(i, t, (in[i] - out[i]) / 2);
    178         }
    179         printf("Case %d: ", K);
    180         if(cnt != 1 || (odd != 0 && odd != 2)){
    181             printf("Poor boy!
    ");
    182         }
    183         else if(sap(s, t, 28) == sum){
    184             printf("Well done!
    ");
    185         }
    186         else{
    187             printf("Poor boy!
    ");
    188         }
    189     }
    190     return 0;
    191 }
  • 相关阅读:
    C#和C实现通过CRC-16 (Modbus)获取CRC值并校验数据(代码)
    c#串口通信类代码可以直接调用
    栈的理解以及如何计算程序所需栈的大小并在IAR中设置栈
    Heap堆的理解以及在IAR中如何设置堆的大小
    ARM Cortex-M0权威指南高清中文版pdf免费分享下载
    如何重新划分linux分区大小
    Using Internal EEPROM of PIC Microcontroller
    树莓派Odroid等卡片式电脑上搭建NAS教程系列6-miniDLNA
    './mysql-bin.index' not found (Errcode: 13) 的解决方法
    移植mysql到嵌入式ARM平台
  • 原文地址:https://www.cnblogs.com/zny0222/p/14598527.html
Copyright © 2011-2022 走看看