思路比较新颖
第一眼看到这个题的时候,直接反应是拆点+费用流,直接就写,后来发现思路假了。
首先为什么不是费用流,因为两个不同点的奶牛可以同时移动,这种情况下产生的费用就不是费用和而是费用max。
举个例子,奶牛A 1->2 , B 2->3 这个过程是同时的,产生的费用显然不是和。
正解应当是二分+最大流+floyd,通过floyd将距离作为建边的限制条件,然后跑最大流,二分check。
另外比较坑的一点,就是初始化不能1e18,因为200*1e16=2e18
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define re int
#define void inline void
#define eps 1e-5
//#define mod 1e9+7
//#define ls(p) p<<1
//#define rs(p) p<<1|1
//#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
#define fi first
#define se second
#define unordered_map map
//#define __int128 long long
using namespace std;
using namespace __gnu_pbds;
const int M=1e7+5;
const int mod=1e9;
const int N=2e6+5;
ll s[N],p[N],all;
int n,m,S,T;
ll f[405][405];
namespace GP
{
struct node
{
int ver,next;
ll edge;
}e[N];
int tot,head[N];
int d[N],gap[N];
void init()
{
for(re i=S;i<=T;i++) head[i]=0;
tot=1;
}
void add(int x,int y,ll z)
{
e[++tot].ver=y;
e[tot].edge=z;
e[tot].next=head[x];
head[x]=tot;
}
void addedge(int x,int y,ll z)
{
add(x,y,z);add(y,x,0);
}
void floyd()
{
for(re k=1;k<=n;k++) for(re i=1;i<=n;i++) for(re j=1;j<=n;j++) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
void bfs()
{
queue < int > q;
for(re i=S;i<=T;i++) d[i]=gap[i]=0;
q.push(T);d[T]=gap[1]=1;
while(q.size())
{
int x=q.front();q.pop();
for(re i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
if(d[y]) continue;
d[y]=d[x]+1;
gap[d[y]]++;
q.push(y);
}
}
}
ll dfs(int x,ll flow)
{
if(x==T) return flow;
ll rest=0;
for(re i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
ll z=e[i].edge;
if(!z) continue;
if(d[x]!=d[y]+1) continue;
ll k=dfs(y,min(z,flow-rest));
if(k<=0) continue;
e[i].edge-=k;
e[i^1].edge+=k;
rest+=k;
if(flow==rest) return rest;
}
if(--gap[d[x]]==0) d[S]=2*T+5;
++gap[++d[x]];
return rest;
}
ll isap()
{
ll maxflow=0;
bfs();
while(d[S]<=T*2) maxflow+=dfs(S,1e18);
return maxflow;
}
void build(ll mid)
{
init();
for(re i=1;i<=n;i++) for(re j=1;j<=n;j++) if(f[i][j]<=mid) addedge(i,j+n,1e18);
for(re i=1;i<=n;i++) addedge(S,i,s[i]),addedge(i+n,T,p[i]);
}
}
bool ck(ll mid)
{
GP::build(mid);
return GP::isap()==all;
}
void solve()
{
cin>>n>>m;
S=0,T=2*n+1;
for(re i=0;i<=2*n+1;i++) for(re j=0;j<=2*n+1;j++) f[i][j]=4e18;
for(re i=0;i<=2*n+1;i++) f[i][i]=0;
for(re i=1;i<=n;i++) scanf("%lld%lld",&s[i],&p[i]),all+=s[i];
for(re i=1;i<=m;i++)
{
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
f[x][y]=f[y][x]=min(f[x][y],z);
}
GP::floyd();
ll l=0,r=1e18,ans=-1;
while(l<=r)
{
ll mid=(l+r)>>1;
if(ck(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans<<endl;
}
signed main()
{
// fflush(stdout);
// srand(102321547);
// freopen("D.in", "r", stdin);
// freopen("D2.out", "w", stdout);
// freopen("9.out", "w", stdout);
int T=1;
// cin>>T;
for(re index=1;index<=T;index++)
{
// printf("Case #%d:\n",index);
solve();
// puts("");
}
return 0;
}
/*
1 4
3 4
15 38 45 52 59 36
*/