zoukankan      html  css  js  c++  java
  • POJ 1637 Sightseeing tour 建图+网络流

    题意:

      给定一个混合图,所谓混合图就是图中既有单向边也有双向边,现在求这样的图是否存在欧拉回路。

    分析:

      存在欧拉回路的有向图,必须满足[入度==出度],现在,有些边已经被定向,所以我们直接记录度数即可,对于无向边呢?

      对于这样的边,我们只需要先随便定向,然后记录出入度。(这些边只用来计算出入度,不用于网络流建图)

      然后我们开始建图。现在极有可能有些点是不满足[入度==出度]的,所以我们要通过一些变向操作,使得图中所有点满足判定。

      如果一个点入度和出度的奇偶性不同,那整张图一定是不合法的。因为改变一条边的方向对端点的入度和出度是同时影响的,且是反向的,比如入度加一出度减一,或者出度加一入度减一,因此无论如何,那样的点都不可能满足判定条件的;

      随后,我们对于:

      所有入度>出度的点,从超级源点连一条容量为(入度-出度)/2的边;

      所有出度>入度的点,向超级汇点连一条容量为(出度-入度)/2的边;

      这样,一单位流量的需求,意味着有这么多边需要变向来使图满足判定条件。所以那些边可以变向,我们就使它的贡献为1 。

      所以,对于我们曾随便定向的那些无向边,我们在网络流建图中,向它们相反方向建一条流量为1的边(与我们随便定的向相反)。

      之后检验整张图与源点汇点连得边是否满流,满流则possible,不满则impossible。

    代码:

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<cmath>
     6 #include<queue>
     7 #define ms(a,x) memset(a,x,sizeof(a))
     8 using namespace std;
     9 const int inf=0x3f3f3f3f;
    10 const int N=1005;
    11 struct edge{int x,y,d;}w[N];
    12 struct node{int y,z,nxt;}e[N*2];
    13 int in[N],ot[N],S,T,q[N],h[N],c=1;
    14 int n,m,sm=0,tot=0,d[N],k,cas,flg;
    15 void add(int x,int y,int z){
    16     e[++c]=(node){y,z,h[x]};h[x]=c;
    17     e[++c]=(node){x,0,h[y]};h[y]=c;
    18 } bool bfs(){
    19     int f=1,t=0;ms(d,-1);
    20     q[++t]=S;d[S]=0;
    21     while(f<=t){
    22         int x=q[f++];
    23         for(int i=h[x],y;i;i=e[i].nxt)
    24         if(d[y=e[i].y]==-1&&e[i].z)
    25         d[y]=d[x]+1,q[++t]=y;
    26     } return (d[T]!=-1);
    27 } int dfs(int x,int f){
    28     if(x==T) return f;int w,tmp=0;
    29     for(int i=h[x],y;i;i=e[i].nxt)
    30     if(d[y=e[i].y]==d[x]+1&&e[i].z){
    31         w=dfs(y,min(e[i].z,f-tmp));
    32         if(!w) d[y]=-1;
    33         e[i].z-=w;e[i^1].z+=w;
    34         tmp+=w;if(tmp==f) return f;
    35     } return tmp;
    36 } void dinic(){
    37     while(bfs()) tot+=dfs(S,inf);
    38 } int main(){
    39     scanf("%d",&cas);while(cas--){
    40         scanf("%d%d",&n,&m);flg=0;
    41         ms(in,0);ms(ot,0);ms(h,0);
    42         c=1;S=0,T=n+1;sm=0,tot=0;
    43         for(int i=1;i<=m;i++)
    44         scanf("%d%d%d",&w[i].x,&w[i].y,&w[i].d),
    45         in[w[i].y]++,ot[w[i].x]++;
    46         for(int i=1;i<=n;i++){
    47             if((in[i]&1)^(ot[i]&1))
    48             {flg=1;break;}
    49             if(in[i]>ot[i]) //sm+=in[i]-ot[i],
    50             add(S,i,(in[i]-ot[i])/2);
    51             if(in[i]<ot[i]) sm+=ot[i]-in[i],
    52             add(i,T,(ot[i]-in[i])/2); 
    53         } if(flg){puts("impossible");continue;}
    54         for(int i=1;i<=m;i++)
    55         if(!w[i].d) add(w[i].y,w[i].x,1);
    56         dinic();sm>>=1;
    57         if(tot==sm) puts("possible");
    58         else puts("impossible");
    59     } return 0;
    60 }
    最大流

      

  • 相关阅读:
    JavaScript事件阶段
    JavaScript阻止事件冒泡
    JavaScript事件冒泡
    JavaScript简单的随机点名系统
    理解Android线程创建流程
    SurfaceFlinger启动篇
    Android系统启动-zygote篇
    Android系统启动-Init篇
    Android系统启动-SystemServer下篇
    Android系统启动-SystemServer上篇
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10242344.html
Copyright © 2011-2022 走看看