• 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

  • 相关阅读:
    关闭弹出窗体,刷新父页面
    Oracle 导出部分表结构,以及导入
    ORCLE报错解决(ora01747:无效的用户.表.列,表.列)
    PL/SQL Developer使用技巧
    自定义table
    Array查询数组中是否包含指定字符
    水晶报表去掉多余小数点
    HttpHandler HttpModule入门篇
    窗口类名无效 错误 解决方法
    2020.10.15
  • 原文地址:https://www.cnblogs.com/yousiki/p/6233078.html
Copyright © 2020-2023  润新知