zoj3229 有源汇上下界最大流

题意:有一个人每天给妹子拍照,每个妹子有最少拍照数,每天有最大拍照数,每天只能给某些特定的妹子拍照,求最大拍照数

题解:很容易看出来的有源汇上下界最大流,对于有源汇 的上下界最大流,我们按照无源汇的操作连边,然后从汇点连一条边到源点,容量无穷大,下界为0,从超级源ss到超级汇tt跑一遍最大流,求得的流量就是可行流 的流量,此时求出来的只是可行流并不是最大流,我们还需要从原来的s到t跑一边最大流,最后的最大流就是可行流 的流量+新增广的s-t流量

ps:这题样例一直过不了,但是我发现很多博客代码的样例输出结果和我的一样= =。还有这题已经挂了,判不出来,一直是Judge Internal Error,所以不知道代码对不对,先放着。

#include<bits/stdc++.h>
#include<ext/rope>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
using namespace __gnu_cxx;

const double g=10.0,eps=1e-7;
const int N=2000+10,maxn=400000+10,inf=0x3f3f3f;

struct edge{
    int from,to,Next,c,low;
}e[maxn<<1];
int dis[N];
int cnt,head[N];
int in[N],out[N];
int ansid[maxn];
void add(int u,int v,int c,int low)
{
    out[u]+=low;
    in[v]+=low;
    e[cnt].from=u;
    e[cnt].to=v;
    e[cnt].low=low;
    e[cnt].c=c;
    e[cnt].Next=head[u];
    head[u]=cnt++;
    e[cnt].from=v;
    e[cnt].to=u;
    e[cnt].low=low;
    e[cnt].c=0;
    e[cnt].Next=head[v];
    head[v]=cnt++;
}
void init()
{
    cnt=0;
    memset(head,-1,sizeof head);
    memset(in,0,sizeof in);
    memset(out,0,sizeof out);
}
bool bfs(int s,int t)
{
    memset(dis,-1,sizeof dis);
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        if(x==t)return 1;
        for(int i=head[x];~i;i=e[i].Next)
        {
            int te=e[i].to;
            if(dis[te]==-1&&e[i].c>0)
            {
                dis[te]=dis[x]+1;
                q.push(te);
            }
        }
    }
    return 0;
}
int dfs(int x,int mx,int t)
{
    if(x==t)return mx;
    int flow=0;
    for(int i=head[x];~i;i=e[i].Next)
    {
        int te=e[i].to,f;
        if(e[i].c>0&&dis[te]==dis[x]+1&&(f=dfs(te,min(mx-flow,e[i].c),t)))
        {
            e[i].c-=f;
            e[i^1].c+=f;
            flow+=f;
        }
    }
    if(!flow)dis[x]=-2;
    return flow;
}
int maxflow(int s,int t)
{
    int ans=0,f;
    while(bfs(s,t))
    {
        while((f=dfs(s,inf,t)))ans+=f;
    }
    return ans;
}
int main()
{
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    int n,m;
    while(cin>>n>>m)
    {
        init();
        int s=n+m+1,t=n+m+2;//原图
        int ss=n+m+3,tt=n+m+4;//超级源超级汇
        for(int i=1;i<=m;i++)
        {
            int a;
            cin>>a;
            add(n+i,t,inf-a,a);
        }
        int res=0;
        for(int i=1;i<=n;i++)
        {
            int k,d;
            cin>>k>>d;
            add(s,i,d,0);
            while(k--)
            {
                int a,b,c;
                cin>>a>>b>>c;
                ansid[++res]=cnt;
                add(i,n+a+1,c-b,b);
            }
        }
        add(t,s,inf,0);
        int sum=0;
        for(int i=1;i<=n+m+2;i++)
        {
            if(in[i]>out[i])sum+=in[i]-out[i],add(ss,i,in[i]-out[i],0);
            else add(i,tt,out[i]-in[i],0);
        }
        if(sum!=maxflow(ss,tt))cout<<-1<<endl;
        else
        {
            cout<<maxflow(s,t)<<endl;
            for(int i=1;i<=res;i++)
                cout<<e[ansid[i]^1].c+e[ansid[i]].low<<endl;
        }
        cout<<endl;
    }
    return 0;
}
/*******************

********************/

时间: 2024-10-09 09:21:14

zoj3229 有源汇上下界最大流的相关文章

zoj 3229 Shoot the Bullet(有源汇上下界最大流)

Shoot the Bullethttp://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442 Time Limit: 2 Seconds      Memory Limit: 32768 KB      Special Judge Gensokyo is a world which exists quietly beside ours, separated by a mystical border. It is a utopia

有源汇上下界可行流(POJ2396)

题意:给出一个n*m的矩阵的每行和及每列和,还有一些格子的限制,求一组合法方案. 源点向行,汇点向列,连一条上下界均为和的边. 对于某格的限制,从它所在行向所在列连其上下界的边. 求有源汇上下界可行流即可. 具体做法可以从汇点向源点连容量为正无穷的边,转成无源汇上下界可行流. 然后可以新建超级源汇,对于一条下界为l,上界为r的边(x,y),从超级源点向y,x向超级汇点连容量为l的边,x向y连容量为r-l的边. 如果那些容量为l的边没满流,则无解. #include <cstdio> #incl

算法复习——有源汇上下界可行流(bzoj2396)

题目: Description We are supposed to make a budget proposal for this multi-site competition. The budget proposal is a matrix where the rows represent different kinds of expenses and the columns represent different sites. We had a meeting about this, so

POJ2396&amp;ZOJ1994--Budget【有源汇上下界可行流】

链接:http://poj.org/problem?id=2396 题意:给一个n*m的矩阵,给出每行的总和以及每列的总和,再给出某些位置的最小或最大限制,问是否存在可能的矩阵,如果存在输出一种矩阵信息. 思路:这是一个有源汇的上下界可行流,对于这种题,从汇点连一条弧到源点,容量为INF,这不会影响流量平衡条件,并且此时原图转换为了无源汇的上下界可行流,剩下的做法和无源汇一样. 建图:原图源点src连向每个行顶点,容量为每行的和,每个列顶点连向汇点,容量为每个列顶点的和,行顶点和列顶点间也各有一

hdu3157有源汇上下界最小流

题意:有源汇上下界最小流裸题,主要就是输入要用字符串的问题 #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 10000000

sgu176 有源汇上下界最小流

题意:有一堆点和边,1起点,n终点,某些边有可能必须满流,要求满足条件的最小流 解法:按原图建边,满流的即上下界都是容量,但是这样按有源汇上下界可行流求出来的可能不是最小流,那么我们需要开始建边的时候不要建从t到s的边,先跑一边从ss到tt的最大流,然后把该边加上再跑一次从ss到tt的最大流,那么从t到s的反向边流过的流量就是原图的最小流,为什么是这样呢,这是因为当我们第一遍跑最大流的时候,此时没有t到s的这条边,那么图中的流量会尽量按其他的边流,当我们第二次跑最大流的时候,流出来的都是第一次中

[zoj] 3229 Shoot the Bullet || 有源汇上下界最大流

zoj 文文要给幻想乡的女孩子们拍照,一共n天,m个女孩子,每天文文至多拍D[i]张照片,每个女孩子总共要被文文至少拍G[i]次.在第i天,文文可以拍c[i]个女孩子,c[i]个女孩子中每个女孩子在当天被拍的次数是[l,r],求最多可以拍多少张照片,以及每天每个可以拍的女孩子被拍了多少张照片. 有源汇上下界最大流. 先跑有源汇上下界可行流,判断是否可行,若可行则此时跑原图中s到t的最大流即为答案. //代码与题解不符-- #include<cstdio> #include<algorit

[hdu] 3157 Crazy Circuits || 有源汇上下界最小流

原题 有两个正负极n个节点和m个元件,每个元件告诉端点是接在哪个节点上的,并且每个元件有工作的最小电流限制,问使所有元件工作的满足条件的最小电流是多少. 有源汇上下界最小流. 考虑dinic的推流思想,所以在跑完可行流后,减去t到s的最大流就是最小流. 实现方法: 建图时先不加入t到s的inf边,跑最大流,再加入inf边跑最大流.若此刻是可行流,那么加入的t到s的inf边的反向边的权值就是最小流. ll ans=0; ans+=dinic(); add(t,s,inf); ans+=dinic(

poj2396 Budget(有源汇上下界可行流)

[题目链接] http://poj.org/problem?id=2396 [题意] 知道一个矩阵的行列和,且知道一些格子的限制条件,问一个可行的方案. [思路] 设行为X点,列为Y点,构图:连边(s,Xi,sumXi,sumXi)(Yi,t,sumYi,sumYi)(Xi,Yj,down[i][j],up[i][j]). 则问题就是求一个有源汇点st的上下界可行流. 类似于 无源无汇上下界可行流 ,添加附加源汇点ST,边权转化为up-down,由ST向每个点连边保持流量平衡.然后添加(t,s,