zoukankan      html  css  js  c++  java
  • poj 1637 Sightseeing tour

    给定一张m个点s条边混合图(有向边和无向边),求是否存在欧拉回路。

    1<=m<=200.1<=s<=1000.

    混合图欧拉回路需要借助最大流。

    有向图欧拉回路的充要条件:图联通且每个点入度等于出度。所以转化为有向图,将每条无向边任意定向,统计入出度。考虑将一条有向边反向会让点的入出度差的绝对值变化2,即若存在某点入出度之差为奇数,则不存在欧拉回路。

    如果入出度之差为偶数,则建图网络流判断。

    对于每条无向边,按刚才定的向连一条容量为1的边。

    源点向所有出度大于入度的点连一条容量为入出度差绝对值除以2的边。

    所有入度大于出度的点向汇点连一条容量为入出度差绝对值除以2的边。

    跑最大流,若满流则存在欧拉回路,否则不存在。

    若存在,将所有流量不为0的边反向,所有点的入出度差均变为0,即可得到一张存在欧拉回路的有向图。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<queue>
      6 using namespace std;
      7 const int dian=205;
      8 const int bian=3005;
      9 const int INF=0x3f3f3f3f;
     10 int h[dian],ver[bian],val[bian],nxt[bian],ch[dian],cr[dian];
     11 int ru[dian],chu[dian];
     12 int cas,n,m,tot,aa,bb,ok;
     13 int S,T;
     14 int aabs(int a){
     15     if(a<0)
     16         return -a;
     17     return a;
     18 }
     19 void add(int a,int b,int c){
     20     tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot;
     21     tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot;
     22 }
     23 bool tell(){
     24     memset(ch,-1,sizeof(ch));
     25     queue<int>q;
     26     q.push(S);
     27     ch[S]=0;
     28     while(!q.empty()){
     29         int t=q.front();
     30         q.pop();
     31         for(int i=h[t];i;i=nxt[i])
     32             if(ch[ver[i]]==-1&&val[i]){
     33                 ch[ver[i]]=ch[t]+1;
     34                 q.push(ver[i]);
     35             }
     36     }
     37     return ch[T]!=-1;
     38 }
     39 int zeng(int a,int b){
     40     if(a==T)
     41         return b;
     42     int r=0;
     43     for(int i=cr[a];i&&b>r;i=nxt[i])
     44         if(ch[ver[i]]==ch[a]+1&&val[i]){
     45             int t=zeng(ver[i],min(b-r,val[i]));
     46             val[i]-=t,r+=t,val[i^1]+=t;
     47             if(val[i])
     48                 cr[a]=i;
     49         }
     50     if(!r)
     51         ch[a]=-1;
     52     return r;
     53 }
     54 int dinic(){
     55     int r=0,t;
     56     while(tell()){
     57         for(int i=1;i<=n+2;i++)
     58             cr[i]=h[i];
     59         while(t=zeng(S,INF))
     60             r+=t;
     61     }
     62     return r;
     63 }
     64 int main(){
     65     scanf("%d",&cas);
     66     while(cas--){
     67         memset(h,0,sizeof(h));
     68         memset(nxt,0,sizeof(nxt));
     69         memset(ru,0,sizeof(ru));
     70         memset(chu,0,sizeof(chu));
     71         tot=1;
     72         scanf("%d%d",&n,&m);
     73         S=n+1,T=n+2;
     74         for(int i=1;i<=m;i++){
     75             scanf("%d%d%d",&aa,&bb,&ok);
     76             chu[aa]++;
     77             ru[bb]++;
     78             if(!ok)
     79                 add(aa,bb,1);
     80         }
     81         int lala=0;
     82         for(int i=1;i<=n;i++)
     83             if(aabs(ru[i]-chu[i])&1){
     84                 lala=1;
     85                 break;
     86             }
     87         if(lala){
     88             printf("impossible
    ");
     89             continue;
     90         }
     91         int ans=0;
     92         for(int i=1;i<=n;i++){
     93             if(ru[i]==chu[i])
     94                 continue;
     95             if(ru[i]>chu[i])
     96                 add(i,T,(ru[i]-chu[i])/2);
     97             else{
     98                 add(S,i,(chu[i]-ru[i])/2);
     99                 ans+=(chu[i]-ru[i])/2;
    100             }
    101         }
    102         if(dinic()==ans)
    103             printf("possible
    ");
    104         else
    105             printf("impossible
    ");
    106     }
    107     return 0;
    108 }

    PS:代码忘了判图连通,不知道题目有没有保证,poj数据过了,懒得加了就这样吧。

  • 相关阅读:
    BZOJ 2527 Meteors 整体二分
    BZOJ 1176: [Balkan2007]Mokia
    DP杂题2
    点分治
    一些图论模板
    一些字符串的题
    斐波那契+线段树
    BZOJ 2957楼房重建
    POJ
    BZOJ 2002 弹飞绵羊
  • 原文地址:https://www.cnblogs.com/dugudashen/p/6243826.html
Copyright © 2011-2022 走看看