zoukankan      html  css  js  c++  java
  • POJ 2391 floyd+二分+最大流

    题意:

    有N块田,每块田下雨时可以容纳a[i]头牛,每块田现在有b[i]头牛,给出一些田与田之间的无向路径及距离,问下雨时最少多少时间后所有牛都能到避雨的地方。

    题解:

    明显又是二分答案。floyd求取两点间最短路

    PS:要用long long!!!

    一开始我想的是三层的图:

    ①n个点表示n块田    ②和③各n个点(灭个点i和i',拆点限制容量)

    S连①中的点容量a[i],表示一开始有a[i]头奶牛在i点

    ①中的点连②中的i,当且仅当两块田之间的距离小于二分值时

    ②和③对应点相连,限制流量

    ③中的点和T连INF的边

    这样果断tle了。

    后来发现③中的点没有用,直接在②和T之间限流即可,优化后就ac了~

    View Code
      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <iostream>
      6 
      7 #define N 1000
      8 #define M 140000
      9 #define INF 1LL<<55
     10 
     11 using namespace std;
     12 
     13 int head[N],to[M],next[M];
     14 __int64 map[N][N],len[M],l,r,mid,sum,num[N],hold[N];
     15 int q[M*10],layer[N];
     16 int n,m,S,T,cnt,tot;
     17 
     18 struct PX
     19 {
     20     __int64 a,b,c;
     21 }px[M];
     22 
     23 inline bool cmp(const PX &a,const PX &b)
     24 {
     25     return a.c<b.c;
     26 }
     27 
     28 inline void floyd()
     29 {
     30     for(int k=1;k<=n;k++)
     31         for(int i=1;i<=n;i++)
     32             for(int j=1;j<=n;j++)
     33                 map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
     34     for(int i=1;i<=n;i++)
     35         for(int j=1;j<=n;j++)
     36             r=max(r,map[i][j]);
     37 }
     38 
     39 inline void add(int u,int v,__int64 w)
     40 {
     41     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
     42     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
     43 }
     44 
     45 inline void read()
     46 {
     47     memset(head,-1,sizeof head); cnt=0;
     48     for(int i=1;i<=n;i++)
     49     {
     50         for(int j=1;j<=n;j++)
     51             map[i][j]=INF;
     52         map[i][i]=0;
     53     }
     54     r=0; S=0; T=n+n+1;
     55     for(int i=1;i<=n;i++)
     56     {
     57         scanf("%I64d%I64d",&num[i],&hold[i]);
     58         sum+=num[i];
     59     }
     60     __int64 c;
     61     for(int i=1,a,b;i<=m;i++)
     62     {
     63         scanf("%d%d%I64d",&a,&b,&c);
     64         map[a][b]=map[b][a]=min(c,map[a][b]);
     65     }
     66     floyd();
     67     tot=0;
     68     for(int i=1;i<=n;i++)
     69         for(int j=1;j<=n;j++)
     70             px[++tot].a=i,px[tot].b=j,px[tot].c=map[i][j];
     71     sort(px+1,px+1+tot,cmp);
     72 }
     73 
     74 inline void build()
     75 {
     76     memset(head,-1,sizeof head); cnt=0;
     77     for(int i=1;i<=tot;i++)
     78     {
     79         if(px[i].c>mid) break;
     80         add(px[i].a,px[i].b+n,INF);
     81     }
     82     for(int i=1;i<=n;i++)
     83     {
     84         add(i+n,T,hold[i]);
     85         add(S,i,num[i]);
     86     }
     87 }
     88 
     89 inline bool bfs()
     90 {
     91     memset(layer,-1,sizeof layer);
     92     int h=1,t=2,sta;
     93     q[1]=S; layer[S]=0;
     94     while(h<t)
     95     {
     96         sta=q[h++];
     97         for(int i=head[sta];~i;i=next[i])
     98             if(len[i]&&layer[to[i]]<0)
     99             {
    100                 layer[to[i]]=layer[sta]+1;
    101                 q[t++]=to[i];
    102             }
    103     }
    104     return layer[T]!=-1;
    105 }
    106 
    107 inline __int64 find(int u,__int64 cur_flow)
    108 {
    109     if(u==T) return cur_flow;
    110     __int64 res=0,tmp;
    111     for(int i=head[u];~i&&res<cur_flow;i=next[i])
    112         if(len[i]&&layer[to[i]]==layer[u]+1)
    113         {
    114             tmp=find(to[i],min(cur_flow-res,len[i]));
    115             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
    116         }
    117     if(!res) layer[u]=-1;
    118     return res;
    119 }
    120 
    121 __int64 dinic()
    122 {
    123     __int64 ans=0;
    124     while(bfs()) ans+=find(S,INF);
    125     return ans;
    126 }
    127 
    128 inline void go()
    129 {
    130     l=0; 
    131     __int64 ans=-1;
    132     r+=1000;
    133     while(l<=r)
    134     {
    135         mid=(l+r)>>1;
    136         build();
    137         if(dinic()==sum) ans=mid,r=mid-1;
    138         else l=mid+1;
    139     }
    140     if(ans>=INF) puts("-1");
    141     else printf("%I64d\n",ans);
    142 }
    143 
    144 int main()
    145 {
    146     while(scanf("%d%d",&n,&m)!=EOF) read(),go();
    147     return 0;
    148 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    P12 向量组03--极大线性无关组
    超导体
    Matlab中disp、fprintf和sprintf有什么区别?
    点击word页面自动弹出信息检索很烦人
    Postman 官方中文版 v7.25.3
    无法为更新定位行。一些值可能已在最后一次读取后已更改解决办法
    Everything文件查找工具
    Delphi的DataSource事件
    Delphi中inherited问题
    delphi窗体继承
  • 原文地址:https://www.cnblogs.com/proverbs/p/2850379.html
Copyright © 2011-2022 走看看