求最大值最小问题通常都是用二分.
#include<iostream>
#include<cstdio>
#include<cstring>
#define min(a,b) ((a)>(b))?(b):(a)
#define inf 1000100000
#define INF (~(0ULL)) >>1
using namespace std;
int N,n,m;
long long map[205][205];
int in[205],out[205];
int k,dist[510],gap[510],edgeHead[500];//双向边
struct{
int v, cap, next, re;
}edge[500500];
void addEdge(int u,int v,int ca){
edge[k].v=v;
edge[k].cap=ca;
edge[k].next=edgeHead[u];
edge[k].re=k + 1; //这个用来记录此边的反边
edgeHead[u]=k ++;
edge[k].v=u;
edge[k].cap=0;
edge[k].next=edgeHead[v];
edge[k].re=k - 1;
edgeHead[v]=k ++;
}
void build_graph(long long mid){
int i,j;
memset(edgeHead,0,sizeof(edgeHead));
k=1;
for(i=1;i<=n;i++){
addEdge(0,i,in[i]);
addEdge(i+n,2*n+1,out[i]);
for(j=1;j<=n;j++)
if(map[i][j]<=mid)
addEdge(i,j+n,inf);
}
N=2*n+1;
}
int dfs (int p , int limit)
{
if(p==N)return limit;
for(int i=edgeHead[p];i!=0;i=edge[i].next){
int v = edge[i].v;
if(dist[p]==(dist[v]+1) && edge[i].cap>0){
int t=dfs(v,min(limit , edge[i].cap));
if(t<0)return t;//没有增广路了
if(t>0)//更新流
{
edge[i].cap-=t;
edge[edge[i].re].cap+=t;
return t;
}
}
}
int tmp=N+1;
for(int i=edgeHead[p];i!=0;i=edge[i].next){
int v = edge[i].v;
if(edge[i].cap>0)
tmp=min(tmp,dist[v]+1);
}
if(--gap[dist[p]]==0 || dist[0]>N)return -1;//出现断层或回流已满
++gap[dist[p]=tmp];
return 0;
}
int SAP()
{
gap[0]=N+1;
int f = 0 , t=0;
while (~(t=dfs(0,inf))) f+=t;
return f;
}
int main(){
int i,j,sum=0;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d %d",&in[i],&out[i]);
sum+=in[i];
for(j=1;j<=n;j++)
map[i][j]=INF;
map[i][i]=0;
}
for(i=1;i<=m;i++){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
map[u][v]=map[u][v]>w?w:map[u][v];
map[v][u]=map[v][u]>w?w:map[v][u];
}
long long l=0,h=0;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
if(map[i][k]!=INF)
for(j=1;j<=n;j++)
if(map[k][j]!=INF){
if(map[i][j]>map[i][k]+map[k][j]){
map[i][j]=map[i][k]+map[k][j];
}
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(map[i][j]!=INF){
h=h>map[i][j]?h:map[i][j];
}
long long ans=-1;
while(l<=h){
long long mid=(l+h)>>1;
build_graph(mid);
memset(dist,0,sizeof(dist));
memset (gap , 0 , sizeof(gap));
int kk=SAP();
if(kk==sum){
h=mid-1;
ans=mid;
}
else
l=mid+1;
}
printf("%lld\n",ans);
return 0;
}