poj 1637 Sightseeing tour 混合图的欧拉回路

  1. 好难理解..直接就记住吧..
  2. #include <iostream>  
  3. #include <cstdlib>  
  4. #include <cstdio>  
  5. #include <cstring>  
  6. #include <string>  
  7. using namespace std;  
  8.   
  9. const int MAXN = 1010;  
  10. const int MAXM = 50010;  
  11. const int INF = 0x3f3f3f3f;  
  12.   
  13.   
  14. struct Edge  
  15. {  
  16.     int v, f;  
  17.     int next;  
  18. }edge[MAXM];  
  19.   
  20. int n, m;  
  21. int cnt;  
  22. int s, t;  
  23.   
  24. int first[MAXN], level[MAXN];  
  25. int q[MAXN];  
  26. int ind[MAXN], outd[MAXN];  
  27. int totFlow;  
  28.   
  29. void init()  
  30. {  
  31.     cnt = 0;  
  32.     totFlow = 0;  
  33.     memset(first, -1, sizeof(first));  
  34.     memset(ind, 0, sizeof(ind));  
  35.     memset(outd, 0, sizeof(outd));  
  36. }  
  37.   
  38. void read(int u, int v, int f)  
  39. {  
  40.     edge[cnt].v = v, edge[cnt].f = f;  
  41.     edge[cnt].next = first[u], first[u] = cnt++;  
  42. }  
  43.   
  44. void read_graph(int u, int v, int f)  
  45. {  
  46.     read(u, v, f);  
  47.     read(v, u, 0);  
  48. }  
  49.   
  50. int bfs(int s, int t)  
  51. {  
  52.     memset(level, 0, sizeof(level));  
  53.     level[s] = 1;  
  54.     int front = 0, rear = 1;  
  55.     q[front] = s;  
  56.     while(front < rear)  
  57.     {  
  58.         int x = q[front++];  
  59.         if(x == t) return 1;  
  60.         for(int e  = first[x]; e != -1; e = edge[e].next)  
  61.         {  
  62.             int v = edge[e].v, f = edge[e].f;  
  63.             if(!level[v] && f)  
  64.             {  
  65.                 level[v] = level[x] + 1;  
  66.                 q[rear++] = v;  
  67.             }  
  68.         }  
  69.     }  
  70.     return 0;  
  71. }  
  72.   
  73. int dfs(int u, int maxf, int t)  
  74. {  
  75.     if(u == t) return maxf;  
  76.     int ret = 0;  
  77.     for(int e = first[u]; e != -1; e = edge[e].next)  
  78.     {  
  79.         int v = edge[e].v, f = edge[e].f;  
  80.         if(level[v] == level[u] + 1 && f)  
  81.         {  
  82.             int Min = min(maxf-ret, f);  
  83.             f = dfs(v, Min, t);  
  84.             edge[e].f -= f;  
  85.             edge[e^1].f += f;  
  86.             ret += f;  
  87.             if(ret == maxf) return ret;  
  88.         }  
  89.     }  
  90.     return ret;  
  91. }  
  92.   
  93. int Dinic(int s, int t)  
  94. {  
  95.     int ans = 0;  
  96.     while(bfs(s, t)) ans += dfs(s, INF, t);  
  97.     return ans;  
  98. }  
  99.   
  100. void read_case()  
  101. {  
  102.     init();  
  103.     scanf("%d%d", &n, &m);  
  104.     while(m--)  
  105.     {  
  106.         int u, v, flag;  
  107.         scanf("%d%d%d", &u, &v, &flag);  
  108.         outd[u]++, ind[v]++;  
  109.         if(u != v)  
  110.         {  
  111.             if(!flag) read_graph(u, v, 1);  
  112.         }  
  113.     }  
  114. }  
  115.   
  116. int build()  
  117. {  
  118.     int flag = 1;  
  119.     s = 0, t = n+1;  
  120.     for(int i = 1; i <= n; i++)  
  121.     {  
  122.         if((ind[i]+outd[i]) & 1) //出度加入度是奇数   
  123.         {  
  124.             return 0;  
  125.         }  
  126.         else if(outd[i] > ind[i]) //出度大于入度   
  127.         {  
  128.             int dif = outd[i]-ind[i];  
  129.             read_graph(s, i, dif/2);  
  130.             totFlow += dif/2;  
  131.               
  132.         } //可能有入度等于出度的情况,连不连无所谓   
  133.         else  
  134.         {  
  135.             int dif = ind[i]-outd[i];  
  136.             read_graph(i, t, dif/2);  
  137.         }  
  138.     }  
  139.     return 1;  
  140. }  
  141.   
  142. void solve()  
  143. {  
  144.     read_case();  
  145.     int flag = build();  
  146.     int ans = Dinic(s, t);  
  147.     if(!flag) printf("impossible\n");  
  148.     else if(ans >= totFlow) printf("possible\n");  
  149.     else printf("impossible\n");   
  150. }  
  151.   
  152. int main()  
  153. {  
  154.     int T;  
  155.     scanf("%d", &T);  
  156.     while(T--)  
  157.     {  
  158.         solve();  
  159.     }  
  160.     return 0;  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值