• [BZOJ2095][Poi2010]Bridges 二分+网络流


    2095: [Poi2010]Bridges

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 1187  Solved: 408
    [Submit][Status][Discuss]

    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

    注意:通过桥为欧拉回路

    首先我们二分答案,之后我们用可行边建图,发现是混合图的欧拉回路问题,用网络流解决。

    对于无向边,我们给它随意定向,之后看每个点的入度出度之差的绝对值tmp是否为2的倍数。

    对于入度大于出度的点,我们从这个点向汇点连一条容量为tmp/2的边。

    对于入度小于出度的点,我们从源点向这个点连一条容量为tmp/2的边。

    对于每一条无向边,我们沿定的向连一条容量为1的边。

    查询是否满流。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<algorithm>
      7 using namespace std;
      8 int n,m;
      9 int head[2002],cnt;
     10 struct data {
     11     int to,next,w;
     12 }e[80008];
     13 void add(int u,int v,int c){e[cnt].to=v;e[cnt].next=head[u];e[cnt].w=c;head[u]=cnt++;}
     14 struct data1 {
     15     int a,b,c,d;
     16 }t[2002];
     17 int ru[2002],cu[2002];
     18 int q[2002];
     19 bool vis[2002];
     20 int dis[2002];
     21 bool bfs() {
     22     memset(dis,-1,sizeof(dis));
     23     int h=0,t=1;
     24     q[h]=0;
     25     vis[0]=1;
     26     dis[0]=0;
     27     while(h!=t) {
     28         int now=q[h];h++;vis[now]=0;if(h==2000) h=0;
     29         for(int i=head[now];i>=0;i=e[i].next) {
     30             int to=e[i].to;
     31             if(e[i].w>0&&dis[to]<0) {
     32                 dis[to]=dis[now]+1;
     33                 if(!vis[to]){
     34                     vis[to]=1;
     35                     q[t++]=to;if(t==2000)t=0;
     36                 }
     37             }
     38         }
     39     }
     40     return dis[n+1]!=-1;
     41 }
     42 int dfs(int now,int a) {
     43     if(now==n+1||a==0) return a;
     44     int flow=0,f;
     45     for(int i=head[now];i>=0;i=e[i].next) {
     46         int to=e[i].to;
     47         if(dis[to]==dis[now]+1&&e[i].w>0) {
     48             f=dfs(to,min(a,e[i].w));
     49             e[i].w-=f;
     50             e[i^1].w+=f;
     51             flow+=f;
     52             a-=f;
     53             if(a==0) break;
     54         }
     55     }
     56     if(!flow) dis[now]=-1;
     57     return flow;
     58 }
     59 bool check(int mid) {
     60     cnt=0;
     61     memset(head,-1,sizeof(head));
     62     memset(ru,0,sizeof(ru));
     63     memset(cu,0,sizeof(cu));
     64     for(int i=1;i<=m;i++) {
     65         if(t[i].c<=mid) {
     66             if(t[i].d<=mid) {
     67                 add(t[i].a,t[i].b,1);
     68                 add(t[i].b,t[i].a,0);
     69                 cu[t[i].a]++;ru[t[i].b]++;
     70             }
     71             else {cu[t[i].a]++;ru[t[i].b]++;}
     72         }
     73         else if(t[i].d<=mid) {ru[t[i].a]++;cu[t[i].b]++;}
     74         else return 0;
     75     }
     76     int sum=0;
     77     for(int i=1;i<=n;i++) {
     78         if(abs(ru[i]-cu[i])&1) return 0;
     79         int tmp=abs(ru[i]-cu[i]);
     80         if(ru[i]<cu[i]) {add(0,i,tmp/2);add(i,0,0);}
     81         else if(ru[i]>cu[i]) {sum+=tmp/2;add(i,n+1,tmp/2);add(n+1,i,0);}
     82     }
     83     int ans=0;
     84     while(bfs()){ans+=dfs(0,2147483647);}
     85     return ans==sum;
     86 }
     87 int main() {
     88     scanf("%d%d",&n,&m);
     89     for(int i=1;i<=m;i++) {
     90         scanf("%d%d%d%d",&t[i].a,&t[i].b,&t[i].c,&t[i].d);
     91     }
     92     int l=0,r=1000;
     93     while(l<=r) {
     94         int mid=(l+r)>>1;
     95         if(check(mid)) r=mid-1;
     96         else l=mid+1;
     97     }
     98     if(r==1000) printf("NIE");
     99     else printf("%d",r+1);
    100 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    redis list 清空记录小技巧
    fastJson 之 JSONPath使用
    【移动开发】怎样自己定义ViewGroup
    POJ 3255 Roadblocks
    java带图片的邮件发送方法实现
    android学习二(Activity)
    OpenWRT加入 crontab开机默认运行
    ubuntu14.04启动提示set_sw_state failed
    jekyll bootstrap更改主题theme
    windows API 实现截图
  • 原文地址:https://www.cnblogs.com/wls001/p/7728276.html
Copyright © 2020-2023  润新知