P2402 奶牛隐藏 网络流

  

题目背景

这本是一个非常简单的问题,然而奶牛们由于下雨已经非常混乱,无法完成这一计算,于是这个任务就交给了你。(奶牛混乱的原因看题目描述)

题目描述

在一个农场里有n块田地。某天下午,有一群牛在田地里吃草,他们分散在农场的诸多田地上,农场由m条无向的路连接,每条路有不同的长度。

突然,天降大雨,奶牛们非常混乱,想要快点去躲雨。已知每个田地都建立有一个牛棚,但是每个牛棚只能容纳一定数量的牛躲雨,如果超过这个数量,那多出的牛只能去别的田地躲雨。奶牛们每移动1的距离花费1时间,奶牛们想知道它们全部都躲进牛棚,最少需要多少时间。(即最后一头奶牛最少要花多久才能躲进牛棚)。

输入输出格式

输入格式:

第一行输入两个整数N,M。N表示田地块数,M表示路径数。

接下来N行,每行两个整数S,P,分别表示该田地现在有几头牛以及该田地的牛棚最多可以容纳多少牛。

接下来M行,每行3个整数A,B,C,表示存在一条路径连接A,B,并且它的长度为C。

输出格式:

一个整数表示所有奶牛全都躲进牛棚所用的最少时间。如果无法使全部奶牛都躲进牛棚,输出-1。

输入输出样例

输入样例#1: 复制
3 4 
7 2 
0 4 
2 6 
1 2 40 
3 2 70 
2 3 90 
1 3 120
输出样例#1: 复制
110

说明

【样例解释】

1号点的两只牛直接躲进1号牛棚,剩下的5只中,4只跑去2号点,还有一只从1->2->3,3号点的2只牛也直接躲进去,这样最慢的牛花费的时间是110。

数据范围 : 对于100%的数据,N<=200 M<=1500

看着像网络流   但是求的不是时间的总和  

正解:  二分加跑最大流判断是否是满流

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
const int N=1e6;
const int M=4e6+54;

struct edge {
    int to, next, w;
} e[M << 1];
int head[N], cnt = 1;
void add(int x, int y, int z) {
    e[++cnt] = (edge){y, head[x], z};
    head[x] = cnt;
    e[++cnt] = (edge){x, head[y], 0};
    head[y] = cnt;
}
int level[N];
bool bfs(int s, int t) {
    memset(level, 0, sizeof level);
    queue<int> q;
    level[s] = 1;
    q.push(s);
    while (!q.empty()) {
        int pos = q.front();
        q.pop();
        for (int i = head[pos]; i; i = e[i].next) {
            int nx = e[i].to;
            if (!e[i].w || level[nx]) continue;
            level[nx] = level[pos] + 1;
            q.push(nx);
        }
    }
    return level[t];
}
int dfs(int s, int t, int flow) {
    if (s == t) return flow;
    int ret = 0;
    for (int i = head[s]; flow && i; i = e[i].next) {
        int nx = e[i].to;
        if (level[nx] == level[s] + 1 && e[i].w) {
            int tmp = dfs(nx, t, min(flow, e[i].w));
            e[i].w -= tmp;
            e[i ^ 1].w += tmp;
            flow -= tmp;
            ret += tmp;
        }
    }
    if (!ret) level[s] = 0;
    return ret;
}
int dinic(int s, int t) {
    int ret = 0;
    while (bfs(s, t)) ret += dfs(s, t, inf);
    return ret;
}
int n,m,s,t,a,b,c,r,ans,l,dis[300][300],cownum,cow[N],home[N];

bool build(int x)
{
    CLR(head,0);cnt=1;
    s=n*3+1;t=s+1;

    rep(i,1,n)
    add(s,i,cow[i]),add(i+n,t,home[i]);

    rep(i,1,n)
    rep(j,i+1,n)
    {
        if(dis[i][j]<=x)
        add(i,j+n,inf),add(j,i+n,inf);
    }
    return dinic(s,t)==cownum;
}

int main()
{
    RII(n,m);
    rep(i,1,n)RII(cow[i],home[i]),cownum+=cow[i];

    rep(i,1,n)rep(j,i,n)
    if(i!=j)dis[i][j]=dis[j][i]=inf;
    else dis[i][j]=0;
    l=0,r=0;
    rep(i,1,m)
    {
        int u,v,w;RIII(u,v,w);
        dis[u][v]=dis[v][u]=min(dis[v][u],w);
    }
    rep(i,1,n)
    rep(j,1,n)
    rep(k,1,n)
    dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]),r=max(r,dis[i][j]);

    int ans=inf;
    while(l<=r)
    {
        int m=(l+r)>>1;
        if(build(m))r=m-1,ans=min(ans,m);
        else l=m+1;
    }
    cout<<ans;
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/11233864.html