ZOJ 3496 Assignment | 二分+有上下界网络流

题目:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3496

大概意思:给你一个网络,有源汇,在保证最大流的情况下求下面两个问题答案

1.所有边中流量最大的边流量最小

2.所有边中流量最小的边流量最大



题解:

De了一下午啊啊,之前学的上下界网络流有问题!

对于问题一,我们二分最大流量,每次建图跑最大流,看是不是和之前一样即可

对于问题二,我们同样二分答案lim,这样每条边满足流量限制w[i]∈[lim,c[i]]

这样建图跑有源汇最大流即可.

下面是坑点

之前写的有源汇最大流都是先跑可行流然后把超级源和超级汇删掉再跑,答案还得加加减减,但是就是Wa

后来发现其实并没有那么难,在可行流的残余网络直接再跑一边最大流就是答案

感性证明如下:

因为如果可行的话超级源的所有出边都满流,这样算最大流的时候只会算到t->s的反边上,又因为原来的可行流就在这条边上,这样直接就能算出答案

别忘了输出答案*p

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
typedef long long ll;
#define N 505
#define M 400005
#define INF 0x3f3f3f3f
using namespace std;
ll Case,n,m,t,s,P,ans1,ans2,S,T,ecnt,Maxflow,l,r,u[M],v[M],c[M],mid,Maxc,lim;
ll head[N],lev[N],cur[N],du[N];
queue <ll> q;
struct adj
{
    ll nxt,v,w;
} e[M];
ll read()
{
    ll ret=0,neg=1;
    char j=getchar();
    for (; j>‘9‘ || j<‘0‘; j=getchar())
        if (j==‘-‘) neg=-1;
    for (; j>=‘0‘ && j<=‘9‘; j=getchar())
        ret=ret*10+j-‘0‘;
    return ret*neg;
}
void add(ll u,ll v,ll w)
{
    e[++ecnt].v=v;e[ecnt].w=w;e[ecnt].nxt=head[u];head[u]=ecnt;
    e[++ecnt].v=u;e[ecnt].w=0;e[ecnt].nxt=head[v];head[v]=ecnt;
}
void init()
{
    ecnt=1;
    memset(head,0,sizeof(head));
}
bool Bfs()
{
    while (!q.empty()) q.pop();
    for (ll i=1; i<=lim; i++)
        cur[i]=head[i],lev[i]=-1;
    q.push(S),lev[S]=1;
    while (!q.empty())
    {
        ll u=q.front();
        q.pop();
        for (ll i=head[u],v; i; i=e[i].nxt)
            if (lev[v=e[i].v]==-1 && e[i].w>0)
            {
                q.push(v),lev[v]=lev[u]+1;
                if (v==T) return 1;
            }
    }
    return 0;
}
ll Dfs(ll u,ll flow)
{
    if (u==T) return flow;
    ll ret=0,delta;
    for (ll &i=cur[u],v; i; i=e[i].nxt)
        if (e[i].w>0 && lev[v=e[i].v]==lev[u]+1)
        {
            delta=Dfs(v,min(e[i].w,flow-ret));
            if (delta)
            {
                e[i].w-=delta;
                e[i^1].w+=delta;
                ret+=delta;
                if (ret==flow) break;
            }
        }
    return ret;
}
ll getG(ll lim)
{
    ll sum=0,tmp=0;
    init();
    add(t,s,INF);S=n+1,T=n+2;
    memset(du,0,sizeof(du));
    for (ll i=1; i<=m; i++)
        if (c[i]-lim<0) return -1;
        else add(u[i],v[i],c[i]-lim),du[u[i]]-=lim,du[v[i]]+=lim;
    for (ll i=1; i<=n; i++)
    {
        if (du[i]>0) add(S,i,du[i]),sum+=du[i];
        if (du[i]<0) add(i,T,-du[i]);
    }
    while (Bfs()) tmp+=Dfs(S,INF);
    if (tmp!=sum) return -1;
    tmp=0;S=s;T=t;
    while (Bfs()) tmp+=Dfs(S,INF);
    return tmp;
}
int main()
{
    Case=read();
    while (Case--)
    {
        n=read(),m=read(),s=read(),t=read(),P=read();
        init();
        S=++s;T=++t;
        Maxflow=Maxc=l=0;
        lim=n+2;
        for (ll i=1; i<=m; i++)
            u[i]=read(),v[i]=read(),c[i]=read(),add(++u[i],++v[i],c[i]),r=Maxc=max(Maxc,c[i]);
        while (Bfs()) Maxflow+=Dfs(S,INF);
        while (l<r)
        {
            init();
            ll mid=l+r>>1,tmp=0;
            for (ll i=1; i<=m; i++) add(u[i],v[i],min(c[i],mid));
            while (Bfs()) tmp+=Dfs(S,INF);
            if (tmp==Maxflow) r=mid;
            else l=mid+1;
        }
        ans1=l;l=0;r=Maxc;
        while (l<r)
        {
            ll mid=l+r+1>>1,tmp=0;
            if (getG(mid)==Maxflow) l=mid;
            else r=mid-1;
        }
        ans2=l;
        printf("%lld %lld\n",1ll*ans1*P,1ll*ans2*P);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/mrsheep/p/8215489.html

时间: 2024-08-01 18:21:43

ZOJ 3496 Assignment | 二分+有上下界网络流的相关文章

[zoj] 3496 Assignment || 有源汇上下界最大流

原题 贴个博客吧 #include<cstdio> #include<algorithm> #include<cstring> #define N 510 #define M 10010 #define inf 0x3f3f3f3f typedef long long ll; using namespace std; struct hhh { int to,next; ll w; }edge[2*M]; int Q,n,m,s,t,p,ss,tt,sum,q[N],x,

BZOJ 2406 二分+有上下界的网络流判定

思路: 求出每行的和  sum_row 每列的和   sum_line 二分最后的答案mid S->i  流量[sum_row[i]-mid,sum_row[i]+mid] i->n+j 流量[L,R] n+j->T 流量 [sum_line[i]-mid,sum_line[i]+mid] 套用有上下界的网络流 判一下就好了.. 这是道有上下界网络流的裸题 //By SiriusRen #include <queue> #include <cstdio> #inc

ZOJ Problem Set - 3229 Shoot the Bullet 【有上下界网络流+流量输出】

题目:ZOJ Problem Set - 3229 Shoot the Bullet 分类:有源有汇有上下界网络流 题意:有 n 天和 m 个girls,然后每天给一部分girls拍照,每个girls 有拍照的下限,即最少要拍这么多张,然后每天有k个女孩拍照,摄影师最多可以拍num张,然后 k 个女该每天拍照数量值有上下限,然后问你有没有满足这样条件的给女孩拍照的最大方案,然后按照输入输出每天给女孩拍照的张数. 做这道题目推荐先做:这儿 分析:首先它让你判断能不能满足条件. 按照题目给出的条件很

【上下界网络流 二分】bzoj2406: 矩阵

感觉上下界网络流考试碰到也还是写不来啊 Description Input 第一行两个数n.m,表示矩阵的大小. 接下来n行,每行m列,描述矩阵A. 最后一行两个数L,R. Output 第一行,输出最小的答案: HINT 对于100%的数据满足N,M<=200,0<=L<=R<=1000,0<=Aij<=1000 题目分析 二分行列之差的最大值. 原文地址:https://www.cnblogs.com/antiquality/p/10362960.html

【有上下界网络流】【ZOJ】2314 Reactor Cooling

[算法]有上下界网络流-无源汇(循环流) [题解] 无源汇网络流相当于重建图后跑最大流. 循环流要求每个点(或边)的流入量和流出量相等. http://www.cnblogs.com/liu-runda/p/6262832.html http://hzwer.com/3356.html 入度>出度时(in[x]>0)时,需要流出去,所以从源向点引一条边,引诱它流出去. 入度<出度时(in[x]<0)时,需要流进来,所以从点向汇引一条边,引诱它流进来. 为何这样正确?源和汇的作用只是

ZOJ 2314 Reactor Cooling 无源汇有上下界网络流

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1314 题意:给出N个点,M条边的有向图,每条边的有上下界规定,问是否存在一个可行流满足条件,如果满足输出YES并输出每条边的流量. 如果不满足输出NO. 根据周源的<一种简易的方法求解流量有上下界的网络中网络流问题> 无源汇上下界网络流的做法是: 设边u->v的下界是B(u,v),上界是C(u,v). 设M(i)为对于i结点的流入i的下界总和-流出i的下界总

@总结 - 8@ 上下界网络流等一类网络流问题

目录 @0 - 参考资料@ @1 - 问题引入@ @2 - 上下界可行流@ @3 - 上下界最大流/最小流@ @4 - 上下界费用流@ @5 - 带负环的最小费用流@ @6 - 例题与参考代码实现@ @7 - 一些类似的杂题@ @0 - 参考资料@ menci 的博客 liu_runda 的博客 @1 - 问题引入@ 我们知道,通常情况下,一个合法的流应该具有如下几个性质: (1)(除源点汇点以外)流量守恒:\(\sum f(i, u) = \sum f(u, j)\). (2)斜对称性:\(f

有上下界的网络流2-有源汇带上下界网络流ZOJ3229

ZOJ3229题目大意:一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝可以和C个女神拍照,每天拍照数不能超过D张,而且给每个女神i拍照有数量限制[Li,Ri],对于每个女神n天的拍照总和不能少于Gi,如果有解求屌丝最多能拍多少张照,并求每天给对应女神拍多少张照:否则输出-1. 解题思路:        1.增设一源点st,汇点sd,st到第i天连一条上界为Di下界为0的边,每个女神到汇点连一条下界为Gi上界为正无穷的边,对于每一天,当天到第i个女孩连一条[Li,Ri]的边.        2.

acdream 1211 Reactor Cooling 【上下界网络流 + 输出流量】

题目:acdream 1211 Reactor Cooling 分类:无源无汇的有上下界网络流. 题意: 给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质. 并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li. 例如: 46(4个点,6个pipe) 12 1 3 (1->2上界为3,下界为1) 23 1 3