POJ 1637 Sightseeing tour

Sightseeing tour
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 9267   Accepted: 3918

Description

The city executive board in Lund wants to construct a sightseeing tour by bus in Lund, so that tourists can see every corner of the beautiful city. They want to construct the tour so that every street in the city is visited exactly once. The bus should also start and end at the same junction. As in any city, the streets are either one-way or two-way, traffic rules that must be obeyed by the tour bus. Help the executive board and determine if it's possible to construct a sightseeing tour under these constraints.

Input

On the first line of the input is a single positive integer n, telling the number of test scenarios to follow. Each scenario begins with a line containing two positive integers m and s, 1 <= m <= 200,1 <= s <= 1000 being the number of junctions and streets, respectively. The following s lines contain the streets. Each street is described with three integers, xi, yi, and di, 1 <= xi,yi <= m, 0 <= di <= 1, where xi and yi are the junctions connected by a street. If di=1, then the street is a one-way street (going from xi to yi), otherwise it's a two-way street. You may assume that there exists a junction from where all other junctions can be reached.

Output

For each scenario, output one line containing the text "possible" or "impossible", whether or not it's possible to construct a sightseeing tour.

Sample Input

4
5 8
2 1 0
1 3 0
4 1 1
1 5 0
5 4 1
3 4 0
4 2 1
2 2 0
4 4
1 2 1
2 3 0
3 4 0
1 4 1
3 3
1 2 0
2 3 0
3 2 0
3 4
1 2 0
2 3 1
1 2 0
3 2 0

Sample Output

possible
impossible
impossible
possible

Source

[Submit]   [Go Back]   [Status]   [Discuss]

 

网络流 —— 混合图的欧拉回路

 

给出一张既有无向边,也有有向边的混合图,判断是否能找到欧拉回路。注意,无向边只能走一次。

 

考虑有向图的欧拉回路判定——当且仅当所有点的出度=入度时,有向图存在欧拉回路。

发现混合图中无向边事实上也充当着有向边的作用,只是不知道应该怎样安排它的指向而已。

那我们不妨先假设一下它的方向,这样就可以得到图中所有点的入度和出度。用cnt_i表示i点的出度-入度。

可以判断,如果此时存在一个点的cnt值为奇数,那这张图一定不存在欧拉回路,因为如何更改该点的入度都不可能等于出度。

此时考虑,加入存在一条无向边的假设指向不对,我们进行更改,将其方向反转,造成的影响是cnt_u减小2,而cnt_v增加2。这里的u,v分别指原指向的出点和入点。

那我们可以构造网络流了:从源点向每个cnt>0的点连cnt_i的边,表示有cnt_i富余的流量;每个cnt<0的点向汇点连cnt_i的边,表示有cnt_i的不足流量;每条无向边,从u向v连2的边,表示反向这条边会造成的影响。跑最大流,如果满流,则可以通过适当的无向边反转得到欧拉回路。其中满流的无向边就是需要反转的边,当然这道题没有要求输出方案就是了。

一个容易想到的优化是,既然所有容量都是偶数,何不直接对每个容量除以2,虽然不一定有啥用,但总不会慢吧?

 

  1 #include <cstdio>
  2 #include <cstring>
  3 
  4 inline int get_c(void)
  5 {
  6     static const int siz = 1024;
  7 
  8     static char buf[siz];
  9     static char *head = buf + siz;
 10     static char *tail = buf + siz;
 11 
 12     if (head == tail)
 13         fread(head = buf, 1, siz, stdin);
 14 
 15     return *head++;
 16 }
 17 
 18 inline int get_i(void)
 19 {
 20     register int ret = 0;
 21     register int neg = false;
 22     register int bit = get_c();
 23 
 24     for (; bit < 48; bit = get_c())
 25         if (bit == '-')neg ^= true;
 26 
 27     for (; bit > 47; bit = get_c())
 28         ret = ret * 10 + bit - 48;
 29 
 30     return neg ? -ret : ret;
 31 }
 32 
 33 template <class T>
 34 inline T min(T a, T b)
 35 {
 36     return a < b ? a : b;
 37 }
 38 
 39 const int inf = 2e9;
 40 const int maxn = 500005;
 41 
 42 int n, m;
 43 
 44 struct edge
 45 {
 46     int u, v, k;
 47 }e[maxn];
 48 
 49 int cnt[maxn];
 50 
 51 int s, t;
 52 
 53 int edges;
 54 int hd[maxn];
 55 int to[maxn];
 56 int nt[maxn];
 57 int fl[maxn];
 58 
 59 inline void add(int u, int v, int f)
 60 {
 61     nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
 62     nt[edges] = hd[v]; to[edges] = u; fl[edges] = 0; hd[v] = edges++;
 63 }
 64 
 65 int dep[maxn];
 66 
 67 inline bool bfs(void)
 68 {
 69     static int que[maxn];
 70     static int head, tail;
 71     
 72     memset(dep, 0, sizeof(dep));
 73     head = 0, tail = 0;
 74     que[tail++] = s;
 75     dep[s] = 1;
 76     
 77     while (head != tail)
 78     {
 79         int u = que[head++], v;
 80         
 81         for (int i = hd[u]; ~i; i = nt[i])
 82             if (!dep[v = to[i]] && fl[i])
 83                 dep[que[tail++] = v] = dep[u] + 1;
 84     }
 85     
 86     return dep[t];
 87 }
 88 
 89 int dfs(int u, int f)
 90 {
 91     if (u == t || !f)
 92         return f;
 93         
 94     int used = 0, flow, v;
 95     
 96     for (int i = hd[u]; ~i; i = nt[i])
 97         if (dep[v = to[i]] == dep[u] + 1 && fl[i])
 98         {
 99             flow = dfs(v, min(fl[i], f - used));
100             
101             used += flow;
102             fl[i] -= flow;
103             fl[i^1] += flow;
104         }
105         
106     if (!used)
107         dep[u] = 0;
108         
109     return used;
110 }
111 
112 inline int maxFlow(void)
113 {
114     int maxFlow = 0, newFlow;
115     
116     while (bfs())
117         while (newFlow = dfs(s, inf))
118             maxFlow += newFlow;
119             
120     return maxFlow;
121 }
122 
123 signed main(void)
124 {
125     for (int cas = get_i(); cas--; )
126     {
127         n = get_i();
128         m = get_i();
129         
130         memset(hd, -1, sizeof(hd));
131         memset(cnt, 0, sizeof(cnt));
132         
133         for (int i = 1; i <= m; ++i)
134         {
135             e[i].u = get_i();
136             e[i].v = get_i();
137             e[i].k = get_i();
138             
139             ++cnt[e[i].u];
140             --cnt[e[i].v];
141         }
142         
143         bool flag = false;
144         
145         for (int i = 1; i <= n && !flag; ++i)
146             if (cnt[i] & 1)flag = true;
147             
148         if (flag)
149             puts("impossible");
150         else
151         {
152             s = 0, t = n + 1;
153             
154             for (int i = 1; i <= m; ++i)
155                 if (!e[i].k)
156                     add(e[i].u, e[i].v, 1);
157                     
158             for (int i = 1; i <= n; ++i)
159                 if (cnt[i])
160                 {
161                     if (cnt[i] > 0)
162                         add(s, i, +cnt[i] / 2);
163                     else
164                         add(i, t, -cnt[i] / 2);
165                 }
166                 
167             int sum = 0;
168             
169             for (int i = 1; i <= n; ++i)
170                 if (cnt[i] > 0)
171                     sum += cnt[i] >> 1;
172                     
173             if (sum == maxFlow())
174                 puts("possible");
175             else
176                 puts("impossible");
177         }
178     }
179 }

 

@Author: YouSiki

 

posted @ 2016-12-29 15:07  YouSiki  阅读(152)  评论(0编辑  收藏  举报