http://poj.org/problem?id=2455
题意:从起点到终点边长最长的最小值。走t次且每条边只能走一次,
二分边长;
刚开始用临街矩阵存边,初始化为零,建流量边时出错。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
using namespace std;
#define maxn 202
const int inf=0x7fffffff;
int dis[maxn],pre[maxn];
int edge[maxn][maxn];
int num[maxn];
int n,src,des;
struct ss
{
int u,v,w;
}map[40500];
void bfs() //记录从汇点到源点的距离。
{
for(int i=1;i<=n;i++)
num[i]=0,dis[i]=n;
queue<int>q;
q.push(des);
dis[des]=0;
num[0]=1;
while(!q.empty())
{
int k=q.front();
q.pop();
for(int i=1;i<=n;i++)
if(dis[i]==n&&edge[i][k]>0)
{
dis[i]=dis[k]+1;
q.push(i);
num[dis[i]]++; //此为距离为dis【i】的个数。
}
}
}
int findarc(int i)
{
for(int j=1;j<=n;j++)
if(edge[i][j]>0&&dis[i]==dis[j]+1)
return j;
return -1;
}
int relable(int i) //此为当道这点没有允许弧,找到从这点出发的距离的最小值来更新dis【i】,
{
int mindis=n;
for(int j=1;j<=n;j++)
if(edge[i][j]>0)
mindis=mindis<dis[j]?mindis:dis[j];
return mindis;
}
int sap()
{
bfs();
int maxflow=0,i=src,j,k;
int d;
pre[src]=-1;
while(dis[src]<n)
{
j=findarc(i);
if(j>=0)
{
pre[j]=i;
i=j;
if(i==des)
{
d=inf;
for(k=des;k!=src;k=pre[k])
d=d<edge[pre[k]][k]?d:edge[pre[k]][k];
for(k=des;k!=src;k=pre[k])
{
edge[pre[k]][k]-=d;
edge[k][pre[k]]+=d;
}
maxflow+=d;
i=src;
}
}
else
{
--num[dis[i]];
if(num[dis[i]]==0) return maxflow;
int x=relable(i);
dis[i]=x+1;
num[dis[i]]++;
if(i!=src) i=src;
}
}
return maxflow;
}
int main()
{
//freopen("Input.txt","r",stdin);
int ncase,T;
while(~scanf("%d%d%d",&n,&ncase,&T))
{
int a,b,c;
memset(map,0,sizeof(map));
des=n;src=1;
int low=1000001,high=0;
for(int i=0;i<ncase;i++)
{
scanf("%d%d%d",&a,&b,&c);
map[i].u=a;
map[i].v=b;
map[i].w=c;
if(low>c) low=c;
if(high<c) high=c;
}
//printf("%d %d\n",low,high);
int mid;
while(low<high)
{
memset(edge,0,sizeof(edge));
mid=(low+high)>>1;
for(int i=0;i<ncase;i++)
if(map[i].w<=mid)
{
edge[map[i].u][map[i].v]++;
edge[map[i].v][map[i].u]++;
}
int yy=sap();
// printf(" 中间测试: %d\n",yy);
if(yy>=T) high=mid;
else low=mid+1;
}
printf("%d\n",high);
}
return 0;
}