坐井观天

In the name of dream

导航

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

Posted on 2012-06-16 19:33  一毛_  阅读(180)  评论(0编辑  收藏  举报

题目链接: 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 }