不得不说这个题的变态啊,数据规模居然超int,太变态了。
题目大意是说:有n块草地,一些奶牛在草地上吃草,但是他们怕淋雨,草地间有m条路,一些草地上有避雨点,每个避雨点能容纳的奶牛是有限的,给出通过每条路的时间,问最少需要多少时间能让所有奶牛进入一个避雨点。
思路依然是经典的二分加网络流,
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=410;
const int maxm=100000;
const long long inf=1LL<<50;
const int infs=1<<30;
int f,p,a[maxn],b[maxn];
int e,ed,total,head[maxn],nxt[maxm],pnt[maxm],cost[maxm],level[maxn],q[maxn];
long long map[maxn][maxn],l,r;
void Read()
{
total=l=r=0;
for(int i=1;i<=f;i++)
{
scanf("%d%d",&a[i],&b[i]);
total+=a[i];
}
for(int i=1;i<=f;i++)
for(int j=1;j<=i;j++)
map[i][j]=map[j][i]=inf;
for(int i=1;i<=p;i++)
{
int u,v;
long long c;
scanf("%d%d%lld",&u,&v,&c);
map[u][v]=map[v][u]=min(map[u][v],c);
}
}
void Floyd()
{
for(int k=1;k<=f;k++)
for(int i=1;i<=f;i++)
if(map[i][k]<inf)
for(int j=1;j<=f;j++)
if(map[i][j]>map[i][k]+map[k][j])
{
map[i][j]=map[i][k]+map[k][j];
r=max(r,map[i][j]);
}
}
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(long long val)
{
e=0,ed=2*f+1;
memset(head,-1,sizeof(head));
for(int i=1;i<=f;i++)
{
AddEdge(0,i,a[i]);
AddEdge(i,f+i,infs);
AddEdge(f+i,ed,b[i]);
}
for(int i=1;i<=f;i++)
for(int j=1;j<i;j++)
if(i!=j&&map[i][j]<=val)
{
AddEdge(j,i+f,infs);
AddEdge(i,f+j,infs);
}
}
bool BFS(int st)
{
memset(level,0,sizeof(level));
int pre=0,last=1;
level[st]=1;
q[0]=st;
while(pre<last)
{
if(q[pre]==ed)
return true;
for(int i=head[q[pre]];i!=-1;i=nxt[i])
{
int v=pnt[i];
if(!level[v]&&cost[i])
{
level[v]=level[q[pre]]+1;
q[last++]=v;
}
}
pre++;
}
return level[ed];
}
long long DFS(int u,int sum)
{
if(u==ed)
return sum;
for(int i=head[u],t;sum&&i!=-1;i=nxt[i])
if(cost[i]&&level[pnt[i]]==level[u]+1&&(t=DFS(pnt[i],min(sum,cost[i]))))
{
cost[i]-=t;
cost[i^1]+=t;
return t;
}
return level[u]=0;
}
long long Go()
{
long long ans=-1;
r+=10;
while(l<r)
{
long long mid=(l+r)>>1;
BuildGraph(mid);
long long sum=0;
while(BFS(0))
while(1)
{
int val=DFS(0,infs);
if(!val)
break;
sum+=val;
}
if(sum==total)
r=ans=mid;
else
l=mid+1;
}
return ans;
}
int main()
{
while(scanf("%d%d",&f,&p)!=EOF)
{
Read();
Floyd();
printf("%lld\n",Go());
}
return 0;
}