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