zoukankan      html  css  js  c++  java
  • [BZOJ2095][Poi2010]Bridges 最大流(混合图欧拉回路)

    2095: [Poi2010]Bridges

    Time Limit: 10 Sec  Memory Limit: 259 MB

    Description

    YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛。现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1。霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线。

    Input

    输入:第一行为两个用空格隔开的整数n(2<=n<=1000),m(1<=m<=2000),接下来读入m行由空格隔开的4个整数a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000),表示第i+1行第i座桥连接小岛a和b,从a到b承受的风力为c,从b到a承受的风力为d。

    Output

    输出:如果无法完成减肥计划,则输出NIE,否则第一行输出承受风力的最大值(要使它最小)

    Sample Input

    4 4
    1 2 2 4
    2 3 3 4
    3 4 4 4
    4 1 5 4

    Sample Output

    4

    HINT

    注意:通过桥为欧拉回路
     
    题解:注意到“最大值最小”这一关键词,不难转化为想到二分答案判合法性问题。
    那么我们接下来要判断的就是“混合图是否存在欧拉回路”这一问题。
    我们考虑先给无向边规定一个方向,但是在这种定义下,得到的图未必是一个欧拉图,即有的点入度大于出度,有的点出度大于入度。
    接下来我们考虑给已经定向的无向边“反向”。
    设i点入度与出度的差值为delta[i],那么对于每个点,delta[i]显然一定是偶数,因为连着它的一条边反向就会造成±2的改变;
    那么我们要做到工作就是“反转”某些边,使得delta全为0为了实现目的,我们:
    从源点向入度大于出度的点连流量为入度减出度/2的边,从入度小于出度向汇点的点连流量为出度减入度/2的边;
    如果这样的边能够跑满,那么这个点就得到了完全的调整。
    对一条无向边,连这条边的方向反向,流量为1的边,表示将这条边反向,两个点的入度与出度得到调整;
    对这个网络求最大流就调整了尽可能多的无向边,源点和汇点所连边的流量都跑满时,
    所有需要调整的边都被调整,出现了欧拉回路。
    所以我们一开始记录一下与源点相连的边的流量和sum,再跑一边dinic/ISAP看是否满流即可。
    代码实现:
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int N=1010,M=2010,inf=0x7fffffff;
     6 struct edge{int zhong,next,flow;};
     7 int a[M],b[M],c[M],d[M],delta[N],n,sum,m;
     8 struct NetWork_Flow
     9 {
    10     edge s[M<<3];
    11     int S,T,e,adj[N],cur[N];
    12     int dist[N],hd,tl,q[N],cnt[N];
    13     inline void add(int qi,int zhong,int flow)
    14         {s[++e].zhong=zhong,s[e].next=adj[qi],adj[qi]=e,s[e].flow=flow;}
    15     inline void bfs()
    16     {
    17         memset(cnt,0,sizeof(cnt)),memset(dist,0,sizeof(dist));
    18         hd=1,tl=0,dist[T]=1,q[++tl]=T;
    19         register int i,x;
    20         while(hd<=tl)
    21             for(x=q[hd++],++cnt[dist[x]],i=adj[x];i;i=s[i].next)
    22                 if(s[i^1].flow&&!dist[s[i].zhong])
    23                     dist[s[i].zhong]=dist[x]+1,q[++tl]=s[i].zhong;
    24     }
    25     inline int Shoot(int rt,int maxf)
    26     {
    27         if(rt==T||!maxf)return maxf;
    28         register int i,x,u,f,ret=0;
    29         for(i=cur[rt];i;i=s[i].next)
    30             if(dist[s[i].zhong]+1==dist[rt])
    31             {
    32                 f=Shoot(s[i].zhong,min(maxf,s[i].flow));
    33                 ret+=f,maxf-=f,s[i].flow-=f,s[i^1].flow+=f;
    34                 if(!maxf)return ret;
    35             }
    36         if(!(--cnt[dist[rt]]))dist[S]=T+2;
    37         ++cnt[++dist[rt]],cur[rt]=adj[rt];
    38         return ret;
    39     }
    40     inline int ISAP()
    41     {
    42         register int i;
    43         memcpy(cur,adj,sizeof(adj));
    44         int maxf=0;bfs();
    45         while(dist[S]<=T+1)maxf+=Shoot(S,inf);
    46         return maxf;
    47     }
    48     inline void build(int val)
    49     {
    50         register int i;
    51         e=1,sum=0,memset(adj,0,sizeof(adj));
    52         memset(delta,0,sizeof(delta));
    53         for(i=1;i<=m;++i)
    54         {
    55             if(c[i]<=val)--delta[a[i]],++delta[b[i]];
    56             if(d[i]<=val)
    57                 add(b[i],a[i],1),add(a[i],b[i],0);
    58         }
    59         for(i=1;i<=n;++i)
    60             if(delta[i]>0)sum+=delta[i]/2,add(S,i,delta[i]/2),add(i,S,0);
    61             else add(i,T,-delta[i]/2),add(T,i,0);
    62     }
    63     inline bool check(int val)
    64     {
    65         register int i;
    66         build(val);
    67         for(i=1;i<=n;++i)
    68             if(delta[i]&1)return 0;
    69         return ISAP()==sum;
    70     }
    71 }G;
    72 int main()
    73 {
    74     scanf("%d%d",&n,&m);
    75     G.S=n+1,G.T=n+2;
    76     register int i,j;
    77     int l=1001,r=0,mi,ans=inf;
    78     for(i=1;i<=m;++i)
    79     {
    80         scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
    81         if(c[i]>d[i])swap(c[i],d[i]),swap(a[i],b[i]);
    82         l=min(l,c[i]),r=max(r,d[i]);
    83     }
    84     while(l<=r)
    85     {
    86         mi=l+r>>1;
    87         if(G.check(mi))r=mi-1,ans=mi;
    88         else l=mi+1;
    89     }
    90     if(ans==inf)puts("NIE");
    91     else printf("%d
    ",ans);
    92 }
  • 相关阅读:
    uplift model学习笔记
    TensorFlow、Numpy中的axis的理解
    JStorm与Storm源码分析(六)--收集器 IOutputCollector 、OutputCollector
    JStorm与Storm源码分析(一)--nimbus-data
    控制反转(IoC)-解析与实现
    ICA独立成分分析去除EEG伪影
    Boston和MIT研究人员利用脑电信号实时控制机器人
    利用LSTM(长短期记忆网络)来处理脑电数据
    EEG数据、伪影的查看与清洗
    EEG vs MRI vs fMRI vs fNIRS简介
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7588290.html
Copyright © 2011-2022 走看看