http://poj.org/problem?id=2455
二分枚举+网络流,注意有重边的情况
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 250
#define P 40050
struct node
{
int u,v,c;
}a[P];
const int inf=0x3f3f3f3f;
int map[N][N],dis[N],cnt[N];
int pre[N],now[N],low[N];
int sap(int n,int s,int t) //顶点为0-n
{
int i,j,k,flow=inf,min,ans=0;
bool flag;
memset(dis,0,sizeof(dis));
memset(cnt,0,sizeof(cnt));
memset(pre,0,sizeof(pre));
for(i=1;i<=n;i++) now[i]=1;
cnt[0]=n;
i=s;
while(dis[s]<n)
{
low[i]=flow;
flag=false;
for(j=now[i];j<=n;j++)
if(map[i][j]>0&&dis[i]==dis[j]+1)
{
now[i]=j;flag=true;
if(map[i][j]<flow) flow=map[i][j];
pre[j]=i;i=j;
if(i==t)
{
ans+=flow;
while(i!=s)
{
k=pre[i];
map[k][i]-=flow;
map[i][k]+=flow;
i=k;
}
flow=inf;
}
break;
}
if(flag) continue;
if(--cnt[dis[i]]==0) break;
for(min=n+1,j=1;j<=n;j++)
if(map[i][j]>0&&dis[j]<min)
{
min=dis[j];
now[i]=j;
}
dis[i]=min+1;
cnt[dis[i]]++;
if(i!=s) //修改顶标后回溯
{
i=pre[i];
flow=low[i];
}
}
return ans;
}
bool cmp(node a,node b)
{
return a.c<b.c;
}
int main()
{
int n,p,t,i,u,v,c,left,right,ans;
while(scanf("%d%d%d",&n,&p,&t)!=EOF)
{
right=0;
for(i=0;i<p;i++)
{
scanf("%d%d%d",&u,&v,&c);
a[i].u=u;a[i].v=v;a[i].c=c;
if(right<c) right=c;
}
sort(a,a+p,cmp);
left=1;
while(left<=right)
{
int mid=(left+right)>>1;
i=0;memset(map,0,sizeof(map));
while(a[i].c<=mid)
{
map[a[i].u][a[i].v]++;//处理重边
map[a[i].v][a[i].u]++;
i++;
}
if(sap(n,1,n)>=t)
{
ans=mid;
right=mid-1;
}
else
left=mid+1;
}
printf("%d\n",ans);
}
return 0;
}