题意:n个牛栏,里面有若干牛,并且有它自己的容量,下雨,牛要避雨,牛栏之间走需要时间,问所有牛都避雨的最少时间。
思路:首先floyd遍,得到两牛栏的最小时间,然后二分枚举时间,看是否达到最大流,想法就这么简单。
感想:这题有点卡时间,我坚持了很久的EK算法终于在这给跪了并且是怎么都起不来的这种状况。。。。于是今早开始看dinic,随便看了看,由于A题心切,就直接照着模版改编着敲了,之后一直wa,知道是long long 范围了还是wa,后来才发现,一个地方值赋错了。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 1<<30
using namespace std;
long long int mm=100000000000000ll;
int m,n,cow[510],con[510],csum,consum;
int fst[510],next[200000],node[200000],c[200000];
int f[200000],en,pre[520],lu[510],dis[510];
int low[520];
long long int l[200000],a[510][510];
bool block[510];
void init()
{
int u,v;
long long int len;
csum=0;
consum=0;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
scanf("%d%d",&cow[i],&con[i]);
csum+=cow[i];
consum+=con[i];
}
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
a[i][j]=mm;
}
a[i][i]=0;
}
for(int i=0; i<m; i++)
{
scanf("%d%d%lld",&u,&v,&len);
if(a[u][v]>len)
{
a[u][v]=a[v][u]=len;
}
}
for(int x=1; x<=n; x++)
{
for(int y=1; y<=n; y++)
{
for(int z=1; z<=n; z++)
{
if(a[y][z]>a[y][x]+a[x][z])
{
a[y][z]=a[y][x]+a[x][z];
}
}
}
}
}
void add(int u,int v,int cc,long long int la)
{
next[en]=fst[u];
fst[u]=en;
node[en]=v;
c[en]=cc;
l[en]=la;
en++;
}
void build(long long int la)
{
memset(fst,-1,sizeof(fst));
en=0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(a[i][j]>la)continue;
add(i,j+n,maxn,a[i][j]);
add(j+n,i,0,a[i][j]);
}
add(0,i,cow[i],0);
add(i,0,0,0);
add(i+n,2*n+1,con[i],0);
add(2*n+1,i+n,0,0);
}
}
void lays(int s,int t)
{
int q[3000],front=0,end=0;
for(int i=s; i<=t; i++)dis[i]=maxn;
q[end++]=s;
dis[s]=0;
while(front<end)
{
int u=q[front++];
for(int i=fst[u]; i!=-1; i=next[i])
{
int v=node[i];
if(dis[v]==maxn&&c[i]>f[i])
{
dis[v]=dis[u]+1;
q[end++]=v;
}
}
}
}
int dinic(int s,int t)
{
int flow=0;
memset(f,0,sizeof(f));
memset(block,0,sizeof(block));
memset(low,0,sizeof(low));
lays(s,t);
int top=s;
while(dis[t]!=maxn)
{
bool flag=false;
low[s]=maxn;
int i,v;
for(i=fst[top]; i!=-1; i=next[i])
{
v=node[i];
if(c[i]>f[i]&&dis[v]==dis[top]+1&&!block[v])
{
flag=true;
break;
}
}
if(flag)
{
low[v]=c[i]-f[i];
if(low[v]>low[top])low[v]=low[top];
pre[v]=top;
top=v;
lu[v]=i;
if(top==t)
{
flow+=low[t];
int j=top;
while(j!=s)
{
int k=lu[j];
f[k]+=low[t];
f[k^1]-=low[t];
j=pre[j];
}
top=s;
memset(low,0,sizeof(low));
}
}
else
{
block[top]=1;
if(top!=s)top=pre[top];
}
if(block[s])
{
lays(s,t);
memset(block,0,sizeof(block));
}
}
return flow;
}
void solve()
{
long long int ans=mm;
long long int high=mm,low=0,mid;
while(low<=high)
{
mid=(low+high)/2;
build(mid);
int aaa=dinic(0,2*n+1);
if(aaa==csum)
{
ans=mid;
high=mid-1;
}
else low=mid+1;
}
if(ans==mm)cout<<-1<<endl;
else cout<<ans<<endl;
}
int main()
{
init();
if(csum>consum)
{
cout<<-1<<endl;
return 0;
}
solve();
return 0;
}