• POJ 2391 floyd + 拆点构图 + 二分 + 最大流


    题目链接: http://poj.org/problem?id=2391

    题目大意:

      F个field,每个field有cow头牛和col个容量,给定field之间的距离,问如果分配合理的话,即每个field容纳允许数量的牛,且每头牛都进入相应的field,那么路程最远的牛的要走的最短路程是多少? (可能需要通过一些field到达指定的field)

    分析:

      首先由floyd求出各个field的最短路map[i][j],

      然后二分枚举答案mid进行构图,超级源点ST向1……F分别连边,容量为相应的col,F+1……F+C分别向超级汇点ED连边,容量为相应的cow,然后对于i (1……F)向 j (F+1……F+C)两两判断是否连边,连边要求是:dis[ i ][ j-F ]<=mid,否则不连,容量为无穷大,然后用sap求出最大流flow与 sum{ cow }比较。

    注意点:

    1、二分答案上限limit的确定,limit= sum( weight )// 即输入的数据认为是一条链那么所有边权之和是一个上限。

    2、距离的初始化为无穷大dis_inf,  dis_inf应该很大很大方便写代码,开始我没弄好数据用了-1表示很麻烦。

    代码:

    poj2391
      1 /*2391    Accepted    952K    204MS    C++    3646B    2012-06-16 08:11:04*/
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <iostream>
      6 #include <algorithm>
      7 #include <vector>
      8 using namespace std;
      9 
     10 #define mpair make_pair
     11 #define pii pair<int,int>
     12 #define MM(a,b) memset(a,b,sizeof(a));
     13 typedef long long lld;
     14 typedef unsigned long long u64;
     15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
     16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
     17 #define maxn 410
     18 #define maxm 82000
     19 const int col_inf= 200000000;
     20 const lld dis_inf= 10000000000000000LL;
     21 
     22 int n,m;
     23 int ST, ED, NV;
     24 int cow[maxn], col[maxn];
     25 lld map[maxn][maxn];
     26 lld limit;
     27 
     28 void Floyd(){
     29     for(int k=1;k<=n;++k)
     30         for(int i=1;i<=n;++i)
     31             if( i!=k && map[i][k]!=dis_inf )
     32                 for(int j=1;j<=n;++j)
     33                     if( j!=i && j!=k && map[k][j]!=dis_inf )
     34                         up_min( map[i][j], map[i][k] + map[k][j] );
     35 }
     36 
     37 int top, head[maxn];
     38 struct Edge{
     39     int v,w,next;
     40     Edge(){}
     41     Edge(int v,int w,int next): v(v), w(w), next(next){}
     42 } edge[maxm];
     43 void Addedge(int u,int v,int w){
     44     edge[top]= Edge( v, w, head[u] );
     45     head[u]= top++;
     46     edge[top]= Edge( u, 0, head[v] );
     47     head[v]= top++;
     48 }
     49 
     50 void build_graph(lld len){
     51     ST= 0; ED= n+n+1, NV= n+n+2;
     52     top= 0;
     53     fill( head, head+NV, -1 ); ///
     54     for(int i=1;i<=n;++i){
     55         if( col[i]>0 ){ ///
     56             Addedge( ST, i, col[i] );
     57             for(int j=1;j<=n;++j)
     58                 if( cow[j]>0 && map[i][j]<=len )
     59                     Addedge( i, n+j, col_inf );
     60         }
     61         if( cow[i]>0 )
     62             Addedge( n+i, ED, cow[i] );
     63     }
     64 }
     65 
     66 int lay[maxn], pre[maxn], gap[maxn], cur[maxn];
     67 int sap(lld mid){
     68     build_graph(mid);
     69 
     70     int ret= 0;
     71     for(int i=0;i<NV;++i) lay[i]= gap[i]= 0, cur[i]= head[i];
     72     int u= pre[ST]= ST; ///
     73     int v, aug= col_inf;
     74     gap[0]= NV;
     75     while( lay[ST]<NV ){
     76         for(int &i= cur[u];i!=-1;i=edge[i].next){
     77             v= edge[i].v;
     78             if( edge[i].w && lay[u]==lay[v]+1 ) break;
     79         }
     80         if( -1!=cur[u] ){
     81             up_min( aug, edge[cur[u]].w );
     82             pre[v]= u;
     83             u= v;
     84             if( v==ED ){
     85                 ret+= aug;
     86                 for(u=pre[u];v!=ST;v=u,u=pre[u]){
     87                     edge[ cur[u] ].w -= aug;
     88                     edge[ cur[u]^1 ].w += aug;
     89                 }
     90                 aug= col_inf;
     91             }
     92         }
     93         else{
     94             int mindis= NV;
     95             for(int i=head[u];i!=-1;i=edge[i].next){
     96                 int v= edge[i].v;
     97                 if( edge[i].w && up_min( mindis, lay[v] ) )
     98                     cur[u]= i;
     99             }
    100             if( --gap[ lay[u] ] == 0 ) break;
    101             ++gap[ lay[u]=mindis+1 ];
    102             u= pre[u];
    103         }
    104     }
    105     return ret;
    106 }
    107 
    108 lld solve(int tot){
    109     lld l=1, r= limit, mid, ret= -1;
    110     while( l<=r ){
    111         mid= (l+r)>>1;
    112         if( sap(mid) == tot ) r= mid-1, ret= mid;
    113         else l= mid+1;
    114     }
    115     return ret;
    116 }
    117 
    118 int main()
    119 {
    120     //freopen("poj2391.in","r",stdin);
    121     while( cin>>n>>m ){
    122         int tot= 0;
    123         for(int i=1;i<=n;++i) scanf("%d%d", cow+i, col+i), tot+= cow[i];
    124         for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) map[i][j]= i==j ? 0 : dis_inf;
    125 
    126         limit= 0;
    127         for(int i=1;i<=m;++i){
    128             int x,y,t;
    129             scanf("%d%d%d", &x, &y, &t);
    130             limit+= t;
    131             if( up_min( map[x][y], (lld)t ) )
    132                 map[y][x]= t;
    133         }
    134         Floyd();
    135 
    136         lld ans= solve( tot );
    137         cout<< ans <<endl;
    138     }
    139 }
    一毛原创作品,转载请注明出处。
  • 相关阅读:
    Extjs combobox设置默认值
    sql 游标循环遍历
    .NET中的DES对称加密
    Asp.Net生命周期
    浅谈C#随机数发生器
    面向对象-多态 附抽象
    c#常用的一些命名空间
    c#面向对象编程基础
    string应用
    [自习任我行]第二阶段任务跟踪10
  • 原文地址:https://www.cnblogs.com/yimao/p/2551714.html
Copyright © 2020-2023  润新知