POJ1637_Sightseeing tour

给一个联通图,有的是单向边,有的是双向边,问是否存在欧拉回路。

乍一看毫无思路,可以这样来搞,对于每条无向边,我们随便指定一个方向,看看是否能够做到所有点的度数之和为偶数。

接下来,对于我们指定的边,假设指定的是U->V,那么我们也同时在网络中设置一条同样的边,使得流量为1,最后如果某点的出入度只差不为0,那么我们把那个差除以2,这表示我们在这个点处至少需要改变多少条无向边的方向。对于出大于入的点,我们连源点,对于如大于出的点,我们连汇点,最后跑最大流看看时候所有的与源点和汇点的边能否满流即可。

一开始的想法是,不指定方向,直接跑最大流,这样是错的,因为无法保证每条无向边最终都被指定了方向,也就是对应回题目里面,不一定无向边都遍历到了,而通过首先指定一个方向,然后再改变方向的方法可以保证这一点。

召唤代码君:

#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 2220
#define maxm 22220
using namespace std;

int to[maxm],next[maxm],first[maxn],c[maxm],edge;
int d[maxn],tag[maxn],can[maxn],dgr[maxn],TAG=520;
int n,m,T,s,t,sum,ans;
int Q[maxn],bot,top;
const int inf=~0U>>1;

void _init()
{
    sum=ans=s=0,t=n+1,edge=-1;
    for (int i=s; i<=t; i++) first[i]=-1,dgr[i]=0;
}

bool check()
{
    for (int i=1; i<=n; i++)
        if (dgr[i]&1) return false;
    return true;
}

void addedge(int U,int V,int W)
{
    edge++;
    to[edge]=V,c[edge]=W,next[edge]=first[U],first[U]=edge;
    edge++;
    to[edge]=U,c[edge]=0,next[edge]=first[V],first[V]=edge;
}

bool bfs()
{
    Q[bot=top=1]=t,d[t]=0,tag[t]=++TAG;
    while (bot<=top)
    {
        int cur=Q[bot++];
        for (int i=first[cur]; i!=-1; i=next[i])
            if (c[i^1]>0 && tag[to[i]]!=TAG)
            {
                tag[to[i]]=TAG,d[to[i]]=d[cur]+1;
                can[to[i]]=false,Q[++top]=to[i];
                if (to[i]==s) return true;
            }
    }
    return false;
}

int dfs(int cur,int num)
{
    if (cur==t) return num;
    int tmp=num,k;
    for (int i=first[cur]; i!=-1; i=next[i])
        if (c[i]>0 && tag[to[i]]==TAG && d[to[i]]==d[cur]-1 && !can[to[i]])
        {
            k=dfs(to[i],min(num,c[i]));
            if (k) num-=k,c[i]-=k,c[i^1]+=k;
            if (num==0) break;
        }
    if (num>0) can[cur]=true;
    return tmp-num;
}

int main()
{
    int U,V,W;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&m);
        _init();
        while (m--)
        {
            scanf("%d%d%d",&U,&V,&W);
            dgr[U]--,dgr[V]++;
            if (W==0) addedge(U,V,1);
        }
        if (!check())
        {
            puts("impossible");
            continue;
        }
        for (int i=1; i<=n; i++)
        {
            if (dgr[i]==0) continue;
            if (dgr[i]<0) addedge(s,i,-dgr[i]/2);
            else
            {
                sum+=dgr[i]/2;
                addedge(i,t,dgr[i]/2);
            }
        }
        while (bfs()) ans+=dfs(s,inf);
        if (ans==sum) puts("possible");
            else puts("impossible");
    }
    return 0;
}

POJ1637_Sightseeing tour

时间: 2024-08-10 23:27:03

POJ1637_Sightseeing tour的相关文章

F - Free DIY Tour(动态规划)

这道题也可以用深搜做,可以深搜本来就不熟,好久没做早忘了,明天看看咋做的 Description Weiwei is a software engineer of ShiningSoft. He has just excellently fulfilled a software project with his fellow workers. His boss is so satisfied with their job that he decide to provide them a free

HDU 1853 Cyclic Tour(最小费用最大流)

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1879    Accepted Submission(s): 938 Problem Description There are N cities in our country, and M one-way roads connecting them. Now L

UVALive 4848 Tour Belt

F - Tour Belt Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 4848 Description Korea has many tourist attractions. One of them is an archipelago (Dadohae in Korean), a cluster of small islands sca

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

Codeforces 490F Treeland Tour(离散化 + 线段树合并)

题目链接 Treeland Tour 题目就是让你求树上LIS 先离散化,然后再线段树上操作.一些细节需要注意一下. #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N =

hdoj 3488 Tour 【最小费用最大流】【KM算法】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2299    Accepted Submission(s): 1151 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

HDU3488 Tour [有向环覆盖 费用流]

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 3159    Accepted Submission(s): 1525 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000

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

Sightseeing tour 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 visit

A Swifr Tour

Tradition suggests that the first program in a new language should print the words "Hello ,world!" on the screen. In Swift , this can be done in a single line :  print("Hello world") If you gave written code in C otr Objective - C , th