• poj1637 Sightseeing tour 网络流 混合图的欧拉回路


    题目链接: http://poj.org/problem?id=1637

    题意:给出N个点,M条路。路有些是双向边,有些是单向边。求是否能找到一个起点,使之遍历所有路正好一次并最后回到起点。

    即判断这个图是否是欧拉回路。

    思路:

    参考:http://www.cnblogs.com/kuangbin/p/3537525.html

    要求是否存在欧拉回路。

    首先判断整个图是否相连,如果不连通,肯定不存在。

    欧拉回路满足条件,每个点的出度 = 入度。

    但因为有双向边的存在,事实上找欧拉回路就是要确定双向边的方向。即定向双向边,如果有一种定向使得整个图为一张有向欧拉图,那么就满足条件

    设D[i] = out[i] - in[i],即i这个点的出度 - 入度。

    要满足条件,则对于所有点D[i] = 0.

    一开始先人为规定无向边的方向,然后求出D[i]。

    假如说原来的边(i->j)改变方向后,对于点i来说,i的出度减少1,i的入度增加1.即out[i]->out[i]-1 in[i]->in[i]+1。

    所以D[i] = out[i] - in[i] = out[i] - 1 - in[i] - 1 减少了2.

    反之则增加2.

    因为最终需要满足的是D[i] = 0,所以如果开始时D[i]是奇数,那么最终肯定不会满足条件。

    排除D[i]是奇数的情况后,一开始先人为的规定无向边的方向,如(i->j)。并且在图中连一条边(i->j),容量为1,表示之后能改变一次方向。

    对于有向边则无需连边。

    增设源点s,汇点t。

    然后对于每个点,如果D[i] > 0,则在s到i,连一条边,容量为D[i]/2.

    如果D[i] < 0,则在i到t,连一条边,容量为-D[i]/2.

    考虑网络中的一条增广路径S-->i-->...-->j-->T,将这条从i到j的路径在G'中全部反向,则:i 的入度加1出度减1,j的入度减1出度加1。

    路径中其它点的入度出度均不变。而i是和S相连的,因此初始D[i]>0,即i的出度大于入度,故这样 反向之后D[i]减少2;

    同理,j是和T相连的,这样反向之后D[j]增加2。因此,若最大流中边<S, i>满流(流量为初始D[i]/2),此时D[i]值就变成了0,也就是i的入度等于出度。

    因此只要使所有S引出的边全部满流,所有初始D 值>0的点的D值将等于0,又因为将边变向后所有点的D值之和不变,所有初始D值小于0的点的D值也将等于0。

    而初始D值等于0的D点既不与S相连 也不与T相连,所以它们是网络中的中间点,而中间点的流入量等于流出量,故它们的入度和出度一直不变,即D值一直为0。因此,整个图G'成为欧拉图。

    求欧拉通路:

    因为对于欧拉通路来说,除了通路的起点和终点外的所有点仍满足D[i] = 0。且起点和终点的D[i]必为奇数。

    所以先求出所有D[i],如果刚好有两个点的D[i]为奇数,则有可能存在欧拉通路。

    如果D[i] > 0 && D[j] < 0 则i为起点,j为终点。连边j->i

    如果D[i] < 0 && D[j] > 0 则j为起点,i为终点。连边i->j

    然后求欧拉回路。

      1 //#include <bits/stdc++.h>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <string>
      6 #include <vector>
      7 #include <queue>
      8 using namespace std;
      9 #define maxn 210
     10 const int inf = 0x3f3f3f3f;
     11 int min(int a, int b)
     12 {
     13     return a<b?a:b;
     14 }
     15 struct Edge
     16 {
     17     int from, to, cap, flow;
     18     Edge(int f, int t, int c, int fl)
     19     {
     20         from = f; to = t; cap = c; flow = fl;
     21     }
     22 };
     23 vector <Edge> edges;
     24 vector <int> G[maxn];
     25 int d[maxn], vis[maxn], cur[maxn];
     26 int s, t, n, m;
     27 void AddEdge(int from, int to, int cap)
     28 {
     29     edges.push_back(Edge(from, to, cap, 0));
     30     edges.push_back(Edge(to, from, 0, 0));
     31     m = edges.size();
     32     G[from].push_back(m-2);
     33     G[to].push_back(m-1);
     34 }
     35 bool bfs()
     36 {
     37     memset(vis, 0, sizeof(vis));
     38     d[s] = 0;
     39     vis[s] = 1;
     40     queue <int> q;
     41     q.push(s);
     42     while(!q.empty())
     43     {
     44         int u = q.front();
     45         q.pop();
     46         for(int i = 0; i < G[u].size(); i++)
     47         {
     48             Edge &e = edges[G[u][i]];
     49             if(!vis[e.to] && e.cap > e.flow)
     50             {
     51                 vis[e.to] = 1;
     52                 d[e.to] = d[u] + 1;
     53                 q.push(e.to);
     54                 
     55             }
     56         }
     57     }
     58     return vis[t];
     59 }
     60 int dfs(int x, int a)
     61 {
     62     if(x == t || a == 0) return a;
     63     int flow = 0, f;
     64     for(int &i = cur[x]; i < G[x].size(); i++)
     65     {
     66         Edge &e = edges[G[x][i]];
     67         if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(e.cap - e.flow, a))) > 0)
     68         {
     69             e.flow += f;
     70             edges[G[x][i]^1].flow -= f;
     71             flow += f;
     72             a -= f;
     73             if(a == 0) break;
     74             
     75         }
     76     }
     77     return flow;
     78 }
     79 int MaxFlow()
     80 {
     81     int flow = 0;
     82     while(bfs())
     83     {
     84         memset(cur, 0, sizeof(cur));
     85         flow += dfs(s, inf);
     86     }
     87     return flow;
     88 }
     89 int T, N, M;
     90 int in[maxn], out[maxn], D[maxn];
     91 int main()
     92 {
     93     scanf("%d", &T);
     94     while(T--)
     95     {
     96         edges.clear();
     97         scanf("%d%d", &N, &M);
     98         for(int i = 0; i <= N+1; i++) G[i].clear();
     99         s = 0; t = N+1;
    100         memset(in, 0, sizeof(in));
    101         memset(out, 0, sizeof(out));
    102         for(int i = 1; i <= M; i++)
    103         {
    104             int a, b, c;
    105             scanf("%d%d%d", &a, &b, &c);
    106             if(c == 0)
    107             {
    108                 out[a]++; in[b]++;
    109                 AddEdge(a, b, 1);
    110             }
    111             else if(c == 1)
    112             {
    113                 out[a]++; in[b]++;
    114             }
    115         }
    116         bool flag = true;
    117         for(int i = 1; i <= N; i++)
    118         {
    119             D[i] = out[i] - in[i];
    120             if(D[i]%2)
    121             {
    122                 flag = false; break;
    123             }
    124             if(D[i] > 0) AddEdge(s, i, D[i]/2);
    125             else if(D[i] < 0) AddEdge(i, t, -D[i]/2);
    126         }
    127         if(flag == false)
    128         {
    129             printf("impossible
    "); continue;
    130         }
    131         int flow = MaxFlow();
    132         flag = true;
    133         for(int i = 0; i < m; i++)
    134         {
    135             Edge &e = edges[i];
    136             if(e.from == s & e.cap != e.flow)
    137             {
    138                 flag = false;
    139                 break;
    140             }
    141         }
    142         if(flag == true) printf("possible
    ");
    143         else printf("impossible
    ");
    144     }
    145     return 0;
    146 }
  • 相关阅读:
    Laravel 服务容器、服务提供器、契约实例讲解
    通过event记录sql
    laravel log改为时间格式
    array_column函数
    linux 安装ssh以及ssh用法与免密登录
    scp复制文件到远程服务器上
    nginx配置ssl证书后无法访问https
    Mac 在terminal 上用命令打开sublime
    Mac上通过iterm 上传文件到服务器
    基于visual Studio2013解决算法导论之044最短路径
  • 原文地址:https://www.cnblogs.com/titicia/p/4788564.html
Copyright © 2020-2023  润新知