![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//题目类型:最大流+二分搜索 //本题的关键在于理解题意:本题不是求最短路,而是要求路上的最长的一部分最小,故可以用二分法解决,至于路的条数,则可以求图的最大流 #include <iostream> #include <queue> //#include <conio.h> using namespace std; #define parray 40001 #define narray 201 const int INF = 10000000; typedef struct edge { int u; int v; int w; }edge; edge edges[parray]; int n,p,t; int r[narray][narray]; int d[narray]; //标号 int num[narray]; //num[i]表示标号为i的顶点数有多少 int pre[narray]; //记录前驱 void ini_d(int s,int t) //BFS计算标号,汇点t标号为0 { int k; queue<int>Q; memset(d,1,sizeof(d)); //将距离设置成为无穷大,此处亦可以使用for循环实现 memset(num,0,sizeof(num)); Q.push(t); d[t]=0; //汇点的标号为0 num[0]=1; while (!Q.empty()) { k=Q.front(),Q.pop(); for (int i=1;i<=n;i++) //遍历所有的结点 { if (d[i]>=n&&r[i][k]>0) //此处要特别注意,通过frontint的值改变其他的距离标号 { d[i]=d[k]+1; Q.push(i); num[d[i]]++; } } } } int findAlowArc(int i) //从i出发寻找允许弧 { int j; for (j=1;j<=n;j++) if (r[i][j]>0&&d[i]==d[j]+1) return j; return -1; } int reLable(int i) //重新标号 { int mm=INF; for (int j=1;j<=n;j++) if (r[i][j]>0) mm=min(mm,d[j]+1); return mm==INF?n:mm; } int maxFlow(int s,int t) //从源点s出发的最大流 { int flow=0,i=s,j; int delta; //增量 memset(pre,-1,sizeof(pre)); while (d[s]<n) { j=findAlowArc(i); if (j>=1) { pre[j]=i; i=j; //从前往后找 if (i==t) //更新残留网络 { delta=INF; for (i=t;i!=s;i=pre[i]) delta=min(delta,r[pre[i]][i]); //找到增广路径的增量 for (i=t;i!=s;i=pre[i]) r[pre[i]][i] -= delta, r[i][pre[i]] += delta; //更改流量 flow += delta; } } else { int x=reLable(i); //重新标号 num[x]++; num[d[i]]--; if (num[d[i]]==0) return flow; //间隙优化 d[i]=x; if (i!=s) i=pre[i]; } } return flow; } void build(int length) { int i,j; memset(r,0,sizeof(r)); for(i=1;i<=p;++i) { if(edges[i].w<=length) { r[edges[i].u][edges[i].v]++; r[edges[i].v][edges[i].u]++; } } } int main() { //freopen("1.txt","r",stdin); int i,j; int src,des; while(scanf("%d%d%d",&n,&p,&t)!=-1) { for(i=1;i<=p;++i) { scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].w); } src = 1; des = n; int l = 0,h = 1000000,mid; while(l<h) { mid = (l+h)/2; build(mid); ini_d(src,des); if(maxFlow(src,des)>=t) h=mid; else l = mid+1; } printf("%d\n",h); } //getch(); return 0; }
别人的标号法最大流模板,收藏学习了。