• POJ 2455 二分+边排序构图+最大流


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

    题目大意:

      从1到n有至少T条无相同道路的路径,即每条边只能用一次,每个点可以多次经过,然后要求所有的路径中最大的边的最小值,每条边只能用一次,注意会有重边。

    分析:

      这个题确实是好题,更确切地说是一道需要非常丰富的经验才可以过的题。

      很容易联想到网络流,求最小的最大可以用二分,用二分出的距离进行限制构图,但是我一直错了,后来也注意到了重边,用了vector<int> map[i][j]来存重边但是一直超时,然后我就看了解题报告了,居然换了一种方式存边并且由于对边进行了排序所以在二分的时候重新构图就非常有效了,这点真的非常值得借鉴,包括二分时上下限的确定取所有边权的最小最大值(可以加速很多)。

      步骤:

      1、 保存所有边按边权从小到大排序,并且确定二分时的上下限;

      2、 二分答案mid;

      3、 对每个mid,构图:  将1中排序后的边选边权w<=mid的边<u,v>,u->v,边权+1, v->u,边权+1;(注意这题无向图并结合题目应该是用双向边),然后跑一遍最大流flow,看flow >= T 是否满足,并更新二分中的l,r;

    代码:

    poj2455
      1 /*2455    Accepted    900K    579MS    C++    2770B    2012-06-16 18:56:23*/
      2 
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <iostream>
      7 #include <algorithm>
      8 #include <vector>
      9 using namespace std;
     10 
     11 #define mpair make_pair
     12 #define pii pair<int,int>
     13 #define MM(a,b) memset(a,b,sizeof(a));
     14 typedef long long lld;
     15 typedef unsigned long long u64;
     16 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
     17 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
     18 #define maxn 210
     19 const int inf= 2100000000;
     20 
     21 int n,m,tot;
     22 int ST,ED;
     23 int g[maxn][maxn];
     24 pair< int, pii > edge[40010];
     25 /// vector<int> map[maxn][maxn];
     26 
     27 bool vis[maxn];
     28 int que[maxn], pre[maxn];
     29 bool bfs(){
     30     fill( vis, vis+1+n, 0 );
     31     int head=0, tail=0;
     32     que[tail++]= ST;
     33     vis[ST]= 1;
     34     while( head<tail ){
     35         int u= que[head++];
     36         for(int v=1;v<=n;++v){
     37             if( g[u][v]>0 && !vis[v] ){
     38                 pre[v]= u;
     39                 if( v==ED ) return 1;
     40                 que[tail++]= v;
     41                 vis[v]= 1;
     42             }
     43         }
     44     }
     45     return 0;
     46 }
     47 
     48 #define x first
     49 #define y second
     50 void build_graph(int len){
     51     for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)g[i][j]= 0;
     52     for(int i=1;i<=m;++i){
     53         if( edge[i].x > len ) break;
     54         ++g[ edge[i].y.x ][ edge[i].y.y ];
     55         ++g[ edge[i].y.y ][ edge[i].y.x ];
     56     }
     57     /*for(int i=1;i<=n;++i)
     58         for(int j=1;j<=n;++j){
     59             g[i][j]= 0;
     60             for(int k=0;k<map[i][j].size();++k)
     61                 g[i][j]+= map[i][j][k]<=len;
     62         }*/
     63 }
     64 
     65 int Edmond_karp(int mid){
     66     build_graph( mid );
     67     int ret= 0;
     68     while( bfs() ){
     69         int t= inf;
     70         for(int i=ED;i!=ST;i=pre[i])
     71             up_min( t, g[pre[i]][i] );
     72         ret+= t;
     73         for(int i=ED;i!=ST;i=pre[i]){
     74             g[pre[i]][i]-= t;
     75             g[i][pre[i]]+= t;
     76         }
     77     }
     78     return ret;
     79 }
     80 
     81 int down, up;
     82 int solve(){
     83     ST= 1, ED= n;
     84     int l=down, r=up, mid;
     85     while( l<=r ){
     86         mid= (l+r)>>1;
     87         if( Edmond_karp(mid) >= tot ) r= mid-1;
     88         else l= mid+1;
     89     }
     90     return l;
     91 }
     92 
     93 int main()
     94 {
     95     //freopen("poj2455.in","r",stdin);
     96     while( cin>>n>>m>>tot ){
     97         up= -inf;
     98         down= inf;
     99         for(int i=1;i<=m;++i){
    100             int u,v,t;
    101             scanf("%d%d%d", &u,&v,&t);
    102             up_max( up, t );
    103             up_min( down, t );
    104             edge[i]= mpair( t, pii( u, v ) );
    105             /// map[x][y].push_back(t);
    106             /// map[y][x].push_back(t);
    107             /// if( up_min( map[x][y], t ) ) map[y][x]= t;
    108         }
    109         /// for(int i=1;i<=n;++i)for(int j=1;j<=n;++j) if( map[i][j]!=inf ) up_max( limit, map[i][j] );
    110         sort( edge+1, edge+1+m );
    111         cout<< solve() <<endl;
    112     }
    113 }
    一毛原创作品,转载请注明出处。
  • 相关阅读:
    微信公众号开发:3、自定义菜单
    微信公众号开发:2、消息处理
    微信公众号开发:1、服务器配置
    基于.NetCore3.1系列 —— 日志记录之初识Serilog
    基于.NetCore3.1系列 —— 日志记录之日志核心要素揭秘
    基于.NetCore3.1系列 —— 日志记录之自定义日志组件
    基于.NetCore3.1系列 —— 日志记录之日志配置揭秘
    基于.NetCore3.1系列 —— 使用Swagger导出文档 (番外篇)
    基于.NetCore3.1系列 —— 使用Swagger导出文档 (补充篇)
    基于.NetCore3.1系列 —— 使用Swagger做Api文档 (下篇)
  • 原文地址:https://www.cnblogs.com/yimao/p/2552043.html
Copyright © 2020-2023  润新知