这个题要求求出能够使得把所有的金子放到仓库里所走过的路的权值最大值最小,
依然采用二分的方法,建图+Dinic跑网络流
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=210;
const int maxm=21000;
const int inf=1<<28;
struct Edge
{
int from;
int to;
int cost;
}E[maxm];
int l,r,e,n,m,st,des,total,res,a[maxn],b[maxn],pnt[maxm],nxt[maxm],cost[maxm],head[maxn],level[maxn],q[maxn];
void Read()
{
total=res=0;
r=0,l=inf;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
total+=a[i];
}
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
res+=b[i];
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int u,v,c;
scanf("%d%d%d",&E[i].from,&E[i].to,&E[i].cost);
l=min(l,E[i].cost);
r=max(r,E[i].cost);
}
}
void AddEdge(int u,int v,int c)
{
pnt[e]=v;nxt[e]=head[u];cost[e]=c;head[u]=e++;
pnt[e]=u;nxt[e]=head[v];cost[e]=0;head[v]=e++;
}
void BuildGraph(int val)
{
e=0,des=n+1,st=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
AddEdge(st,i,a[i]);
for(int i=1;i<=n;i++)
AddEdge(i,des,b[i]);
for(int i=1;i<=m;i++)
if(E[i].cost<=val)
{
AddEdge(E[i].from,E[i].to,inf);
AddEdge(E[i].to,E[i].from,inf);
}
}
bool BFS()
{
memset(level,0,sizeof(level));
level[st]=1;
int pre=0,last=1;
q[pre]=st;
while(pre<last)
{
if(q[pre]==des)
return true;
for(int i=head[q[pre]];i!=-1;i=nxt[i])
if(cost[i]&&!level[pnt[i]])
{
level[pnt[i]]=level[q[pre]]+1;
q[last++]=pnt[i];
}
pre++;
}
return level[des];
}
int DFS(int u,int sum)
{
if(u==des)
return sum;
for(int i=head[u],t;i!=-1;i=nxt[i])
if(cost[i]&&level[pnt[i]]==level[u]+1&&(t=DFS(pnt[i],min(cost[i],sum))))
{
cost[i]-=t;
cost[i^1]+=t;
return t;
}
return level[u]=0;
}
int Go()
{
int ans=-1;
while(l<=r)
{
int mid=(l+r)>>1,sum=0;
BuildGraph(mid);
while(BFS())
while(1)
{
int val=DFS(st,inf);
if(!val)
break;
sum+=val;
}
if(sum==total)
{
r=mid-1;
ans=mid;
}
else
l=mid+1;
}
return ans;
}
int main()
{
while(scanf("%d",&n)&&n)
{
Read();
if(total>res)
{
printf("No Solution\n");
continue;
}
int ans=Go();
if(ans==-1)
printf("No Solution\n");
else
printf("%d\n",ans);
}
return 0;
}