传送门
发现惊天大错误QAQ
T上天然后发现自己的板子是假的QAQ
就是这一句
if(!cur) return flow;
我之前一直写的是break。。。
注意实际意义
我们的dep[x]=-1是当前已经流不满无法増广了所以才把它设为-1不再增广
而流满了表示还可以继续增广所以直接return
我以前一直写的假板子直到这个题T飞。。。一个爆哭。。。
回归正传
这个题我们需要求最小化跑的最远的奶牛的时间
由此可以想到二分
二分以后我们需要找到最远的奶牛,可以通过预处理出两两牛棚的最短路来进行连边
所以最后的图大概是这个样子
对于每一个田地拆成两个点 初始牛和牛棚
源点连牛流量为牛的数量 牛棚连汇点流量为牛棚的容量 对于二分的mid 我们对dis[i][j]<=mid的连边流量为inf
然后看最后是否能满流就可以啦
二分+判断满流也是一个常见套路呢(另外一个是枚举+残存网络加边)
附代码。(注意longlong又一个爆哭)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define inf 1000000000000ll
#define ll long long
using namespace std;
struct edge{int to,lt;ll f;}e[320010],p[3010];
int in[420],cnt,s,t,n,m,ip[420];
queue<int> que;ll dis[420][420],dep[420],tot;
void addpath(int x,int y,ll f)
{
p[++cnt].to=y;p[cnt].lt=ip[x];p[cnt].f=f;ip[x]=cnt;
p[++cnt].to=x;p[cnt].lt=ip[y];p[cnt].f=f;ip[y]=cnt;
}
void add(int x,int y,ll f)
{
e[++cnt].to=y;e[cnt].lt=in[x];e[cnt].f=f;in[x]=cnt;
e[++cnt].to=x;e[cnt].lt=in[y];e[cnt].f=0;in[y]=cnt;
}
void floyd()
{
memset(dis,48,sizeof(dis));//printf("%lld
",dis[0][0]);
for(int i=1;i<=n;i++) dis[i][i]=0;
for(int i=1;i<=n;i++)
for(int j=ip[i];j;j=p[j].lt)
dis[i][p[j].to]=min(dis[i][p[j].to],p[j].f);
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
bool bfs()
{
while(!que.empty()) que.pop();
memset(dep,0,sizeof(dep));
dep[s]=1;que.push(s);
while(!que.empty())
{
int x=que.front();que.pop();
//printf("%d %d
",x,in[x]);printf("QAQ");
for(int i=in[x];i;i=e[i].lt)
{
int y=e[i].to;
if(!dep[y]&&e[i].f)
{
dep[y]=dep[x]+1;
if(y==t) return 1;
que.push(y);
}
}
}
return 0;
}
ll dfs(int x,ll flow)
{
if(x==t||!flow) return flow;
ll cur=flow;
for(int i=in[x];i;i=e[i].lt)
{
int y=e[i].to;
if(dep[y]==dep[x]+1&&e[i].f)
{
ll tmp=dfs(y,min(cur,e[i].f));
e[i].f-=tmp;e[i^1].f+=tmp;cur-=tmp;
if(!cur) return flow;
}
}
dep[x]=-1;
return flow-cur;
}
ll dinic()
{
ll ans=0;
while(bfs()) ans+=dfs(s,inf);
//printf("%d
",ans);
return ans;
}
int cow[400],she[400];
bool check(ll tmp)
{
cnt=1;memset(in,0,sizeof(in));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j ++)
if(dis[i][j]<=tmp) add(i,n+j,inf);
for(int i=1;i<=n;i++) add(s,i,cow[i]),add(n+i,t,she[i]);
ll cur=dinic();
//printf("%lld %lld
",tmp,cur);
return cur==tot;
}
ll erf()
{
ll l=0,r=inf,mid,ans=inf;
while(l<=r)
{
mid=(l+r)>>1;//printf("%lld
",mid);
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
int main()
{
//int n,m;
scanf("%d%d",&n,&m);s=2*n+1;t=s+1;
for(int i=1;i<=n;i++) scanf("%d%d",&cow[i],&she[i]),tot+=cow[i];
for(int i=1;i<=m;i++)
{
int x,y;ll f;
scanf("%d%d%lld",&x,&y,&f);
addpath(x,y,f);
}
floyd();ll ans=erf();
printf("%lld
",ans==inf?-1:ans);
return 0;
}