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


Language:
Default

Sightseeing tour

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 7983   Accepted: 3346

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

Northwestern Europe 2003

题意:求混合图是否有欧拉回路。

思路:首先是基图联通(不考虑度为0的点),然后需要借助网络流来判断。

首先给原图中的无向边随便指定一个方向(初始定向),将原图改为有向图G’,然后的任务就是改变G‘中某些边得方向(当然是无向边转化来的,原 有向边不变)使其满足每个点的入度等于出度。

设d[i]为G‘中(点i的出度-点i的入度)。可知,在改变G‘中边的方向时,任何点的d值的奇偶性都不会变(设将边<i,j>改为<j,i>,则i的入度加1出度减1,j的入度减1出度加1,两者之差加2或减2,奇偶性不变)!而最终要求的是每个点的入度等于出度,即每个点的d值为0,是偶数;故:若初始定向得到的G‘中任意一个点的d值是奇数,那么原图中一定不存在欧拉环!

若初始d值都是偶数,则将G‘改成网络:添加源点S和汇点T,对于每个d[i]>0的点i,连边<S,i>,容量为d[i]/2;对于每个d[i]<0的点j,连边<j,T>,容量为-d[j]/2;G‘中的每条无向边在网络中仍保留,容量为1(表示该边最多只能被改变方向一次)。求这个网络的最大流,若S引出的所有边均满流,则原图是欧拉图,否则不是欧拉图。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 222
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
const int MAXM = 3000;
typedef long long ll;
using namespace std;

struct Edge
{
    int to,next,cap,flow;
}edge[MAXM];

int st,ed;
int d[MAXN];
int tol,m,s;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}

//加边,单向图三个参数,双向图四个参数
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u];
    edge[tol].flow=0; head[u]=tol++;
    edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v];
    edge[tol].flow=0; head[v]=tol++;
}

//输入参数:起点,终点,点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=start;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while (dep[start]<N)
    {
        if (u==end)
        {
            int Min=INF;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                if (Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for (int i=cur[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].to;
            if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if (flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for (int i=head[u];i!=-1;i=edge[i].next)
            if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        gap[dep[u]]--;
        if (!gap[dep[u]]) return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if (u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}

int main()
{
    int i,j,cas,u,v,w;
    sf(cas);
    while (cas--)
    {
        sff(m,s);
        st=0;ed=m+1;
        init();
        mem(d,0);
        FRE(i,1,s)
        {
            sfff(u,v,w);
            d[u]++;
            d[v]--;
            if (w!=1)
                addedge(u,v,1);
        }
        bool flag=true;
        int outflow=0;
        FRE(i,1,m)
        {
            if (abs(d[i])%2==1)
            {
                flag=false;
                break;
            }
            if (d[i]>0)
            {
                addedge(st,i,d[i]/2);
                outflow+=d[i]/2;
            }
            if (d[i]<0)
                addedge(i,ed,abs(d[i])/2);
        }
        if (!flag)
        {
            printf("impossible\n");
            continue;
        }
        int Maxflow=sap(st,ed,m+2);
        if (Maxflow==outflow)
            printf("possible\n");
        else
            printf("impossible\n");
    }
    return 0;
}
/*
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
*/
时间: 2024-11-09 22:14:44

Sightseeing tour (poj 1637 混合图的欧拉回路)的相关文章

POJ 1637 混合图的欧拉回路判定

题意:一张混合图,判断是否存在欧拉回路. 分析参考: 混合图(既有有向边又有无向边的图)中欧拉环.欧拉路径的判定需要借助网络流! (1)欧拉环的判定:一开始当然是判断原图的基图是否连通,若不连通则一定不存在欧拉环或欧拉路径(不考虑度数为0的点). 其实,难点在于图中的无向边,需要对所有的无向边定向(指定一个方向,使之变为有向边),使整个图变成一个有向欧拉图(或有向半欧拉图).若存在一个定向满足此条件,则原图是欧拉图(或半欧拉图)否则不是.关键就是如何定向? 首先给原图中的每条无向边随便指定一个方

网络流 + 欧拉回路 = B - Sightseeing tour POJ - 1637

B - Sightseeing tour POJ - 1637 https://blog.csdn.net/qq_36551189/article/details/80905345 首先要了解一下欧拉回路的基本思路. 欧拉回路:如果是无向图,那么每一个点连的边的数量为偶数,如果是有向图,那么每一个点的入度要等于出度. 欧拉路径:这个欧拉路径是没有成环的,如果是无向图,那么除了两个点连的边是奇数,其他都是偶数, 如果是有向图,那么除了有一个点入度比出度大1,有一个点的出度比入度大1 ,其他都是入度

TOJ 2099 Sightseeing tour(网络流判混合图欧拉回路)

描述 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 s

POJ 1637 混合图欧拉回路

先来复习一下混合图欧拉回路:给定一张含有单向边和双向边的图,使得每一点的入度出度相同. 首先对于有向边来说,它能贡献的入度出度是确定的,我们不予考虑.对于无向图,它可以通过改变方向来改变两端点的出入度.好的,我们不妨先将这些无向边随意定向,因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路,所以我们先扫一遍总度数看看是否为偶数,如果是奇数我们弃疗就好. 接下来我们要尝试着修复这些无向边的方向使得度数平衡.首先细化问题到每一个点:对于点u,如果它的入度大于出度,那

POJ1637 Sightseeing tour(判定混合图欧拉回路)

有向连通图存在欧拉回路的充要条件是所有点入度=出度. 首先随便给定所有无向边一个方向(不妨直接是u->v方向),记录所有点的度(记:度=入度-出度). 这时如果有点的度不等于0,那么就不存在欧拉回路,就需要改变那些无向边的方向. 而改变一个无向边的方向,相当于边上两个端点的入度和出度都变化了1,它们的度±2. 另外,这样可以证明如果这时某个点的度为奇数那么一定不存在存在欧拉回路的解. 构图如下:所有无向边(u,v),建立容量为1的(u,v)边:所有度小于0的点u,建立容量为-deg/2的(vs,

POJ 1637 Sightseeing tour(混合图的欧拉回路)

题目链接 建个图,套个模板. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <algorithm> #include <vector> #include <string> #include <queue> using namespace std; #define INF 0x3ffffff str

poj1637 Sightseeing tour,混合图的欧拉回路问题,最大流解

混合图的欧拉回路问题 题目地址 欧拉回路问题 1 定义 欧拉通路 (Euler tour)--通过图中每条边一次且仅一次,并且过每一顶点的通路. 欧拉回路 (Euler  circuit)--通过图中每条边一次且仅一次,并且过每一顶点的回路. 欧拉图--存在欧拉回路的图.  2 无向图是否具有欧拉通路或回路的判定  G有欧拉通路的充分必要条件为:G 连通,G中只有两个奇度顶点(它们分别是欧拉通路的两个端点). G有欧拉回路(G为欧拉图):G连通,G中均为偶度顶点.  3 有向图是否具有欧拉通路或

bzoj2095: [Poi2010]Bridges(二分+混合图求欧拉回路)

传送门 这篇题解讲的真吼->这里 首先我们可以二分一个答案,然后把所有权值小于这个答案的都加入图中 那么问题就转化为一张混合图(既有有向边又有无向边)中是否存在欧拉回路 首先 无向图存在欧拉回路,当且仅当图的所有顶点度数都为偶数且图连通.        有向图存在欧拉回路,当且仅当图的所有顶点入度等于出度且图连通. 那么我们怎么判断混合图的欧拉回路是否存在呢? 我们把无向边的边随便定向,然后计算每一个点的入度和出度.如果有某一个点的入度和出度之差是奇数,那么肯定不存在欧拉回路. 因为欧拉回路要求

欧拉回路、混合图的欧拉回路

欧拉回路 从一个点开始把图中的边恰好经过一次,再回到出发点,这样的路径就是欧拉回路. 如图就是一个欧拉回路 欧拉回路判定 不过怎么样的图中才存在欧拉回路呢? 欧拉回路分有向图和无向图两种: 有向图: 图中所有点的入度等于出度 无向图: 图中所有点的度数都为偶数 这还是很好理解的,不过你可能要问,怎么知道一个混合图中有没有欧拉回路呢? 混合图的欧拉回路 过程: 先将无向边随意定向 判断每个点的入度和出度是不是同奇偶,不同则无解 用一个超级原点向出度小于入度的点连一条容量为 \({|入度-出度| \