题意:F个地区。已知各个地区之间的行走时间。每个地区I有两个属性:

这个地区当前牛的个数,下雨的时候这个地区实际能够容纳牛的个数。

问至少需要多少时间,使所有的牛在下雨的时候都能够被容纳。

构图:先Floyd求所有点对之间最短路。二分最短时间,源向I连容量为初始牛数的边,I’向汇连容量为所能容纳牛数的边,I向I’连容量无穷大的边,若I,J能够在mid时间内到达,则连无穷大的边,用最大流判可行性。

注意几点:

1.点之间的距离非常大,鄙人宏定义1500000005000,同时注意long long的使用;

2.无向图;

3.自己可以流向自己;

4.拆点:1流向2,2流向3并不意味着1能流向3。

View Code
/*Source Code
Problem: 2391  User: HEU_daoguang
Memory: 3132K  Time: 375MS
Language: G++  Result: Accepted
Source Code*/
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int n,m;
#define infx 1500000005000
#define inf 20000000
#define V 3000
#define E 200000
struct Node{
    int s,t;
}point[V];
long long map[V][V];

int cnt;
int dist[V];
int head[V];
int que[V];
int sta[V];
struct Edge
{
    int u,v,c,next;
}edge[4*E];

void init(){
    cnt=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c){
    edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c;
    edge[cnt].next=head[u];head[u]=cnt++;
    edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=0;
    edge[cnt].next=head[v];head[v]=cnt++;
}

int dinic(int s,int t){
    int ans=0;
    while(true){
        int left,right,u,v;
        memset(dist,-1,sizeof(dist));
        left=right=0;
        que[right++]=s;
        dist[s]=0;

        while(left<right){
            u=que[left++];
            for(int k=head[u];k!=-1;k=edge[k].next){
                u=edge[k].u;
                v=edge[k].v;
                if(edge[k].c > 0 && dist[v]==-1){
                    dist[v]=dist[u]+1;
                    que[right++]=v;
                    if(v==t){
                        left=right;
                        break;
                    }
                }
            }
        }

        if(dist[t]==-1) break;

        int top=0;
        int now=s;

        while(true){
            if(now!=t){
                int k;
                for(k=head[now];k!=-1;k=edge[k].next){
                    if(edge[k].c>0 && dist[edge[k].v]==dist[edge[k].u]+1) break;
                }
                if(k!=-1){
                    sta[top++]=k;
                    now=edge[k].v;
                }
                else{
                    if(top==0) break;
                    dist[edge[sta[--top]].v]=-1;
                    now=edge[sta[top]].u;
                }
            }
            else{
                int flow=inf,ebreak;
                for(int i=0;i<top;i++){
                    if(flow>edge[sta[i]].c){
                        flow=edge[sta[i]].c;
                        ebreak=i;
                    }
                }
                ans+=flow;
                for(int i=0;i<top;i++){
                    edge[sta[i]].c-=flow;
                    edge[sta[i]^1].c+=flow;
                }
                now=edge[sta[ebreak]].u;
                top=ebreak;
            }
        }
    }
    return ans;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int a,b,c,sum;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(i==j) map[i][j]=0;
                else map[i][j]=infx;
            }
        sum=0;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&point[i].s,&point[i].t);
            sum+=point[i].s;
        }
        while(m--){
            scanf("%d%d%d",&a,&b,&c);
            if(c<map[a][b]) map[a][b]=map[b][a]=c;
        }
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                        map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
        long long l=-1,r=infx,mid;
        int flag=0;
        while(l<r){
            mid=(l+r)/2;
            init();
            for(int i=1;i<=n;i++){
                addedge(0,i,point[i].s);
                addedge(i+n,2*n+1,point[i].t);
            }
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(map[i][j]<=mid)
                        addedge(i,j+n,inf);
            if(dinic(0,2*n+1)==sum) r=mid,flag=1;
            else l=mid+1;
        }
        if(flag) printf("%lld\n",r);
        else printf("-1\n");
    }
    return 0;
}