zoukankan      html  css  js  c++  java
  • [poj] 2396 [zoj] 1994 budget || 有源汇的上下界可行流

    poj原题

    zoj原题

    //注意zoj最后一行不要多输出空行

    现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出、列代表不同赛区支出的矩阵。组委会曾经开会讨论过各类支出的总和,以及各赛区所需支出的总和。另外,组委会还讨论了一些特殊的约束条件。组委会的任务是制定一个满足所有约束条件且行列和满足要求的预算。


    有源汇的上下界可行流。

    1、建原图(对于上界Max和下界Min的边连边为Max-Min,像无源汇一样记录extra)
    2、在t和s(原图)见连接一条inf的边,使原图变为无源汇
    3、建虚拟源汇S和T,按无源汇建图
    4、跑最大流
    5、判断是否可行(==sum)

    #include<cstdio>
    #include<algorithm>
    #define N 250
    #define M 100010
    #define inf 0x3f3f3f3f
    #define fir first
    #define sec second
    using namespace std;
    struct hhh
    {
        int to,w,next,f,lower;
    }edge[M];
    int cnt=1,head[N],dis[N],cur[N];
    int TT,n,m,s,t,ans,sum,q[N],r,extra[N],A[N][N];
    int Q,a,b,x;
    char c[3];
    pair <int,int> g[N][N];
    
    int read()
    {
        int ans=0,fu=1;
        char j=getchar();
        for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
        for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
        return ans*fu;
    }
    
    void init()
    {
        ans=sum=0;
        cnt=1;
        for (int i=1;i<=n+m+5;i++)
    	head[i]=extra[i]=0;
    }
    
    int add(int u,int v,int w,int p)
    {
        edge[++cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;edge[cnt].f=0;edge[cnt].lower=p;head[u]=cnt;
        edge[++cnt].to=u;edge[cnt].next=head[v];edge[cnt].w=0;edge[cnt].f=0;edge[cnt].lower=p;head[v]=cnt;
        return cnt-1;
    }
    
    bool ADD(int u,int v,char d,int w)
    {
        pair <int,int> &now=g[u][v];
        if (d=='=')
        {
    	if (now.fir<=w && w<=now.sec) now=make_pair(w,w);
    	else return 0;
        }
        else if (d=='>')
        {
    	w++;
    	if (now.sec>=w) now.fir=max(now.fir,w);
    	else return 0;
        }
        else
        {
    	w--;
    	if (now.fir<=w) now.sec=min(now.sec,w);
    	else return 0;
        }
        return 1;
    }
    
    bool bfs(int S,int T)
    {
        for (int i=0;i<=T;i++)
    	cur[i]=head[i],dis[i]=-1;
        dis[S]=1;
        q[r=1]=S;
        for (int l=1;l<=r;l++)
        {
    	int u=q[l];
    	for (int i=head[u],v;i;i=edge[i].next)
    	    if (edge[i].w>edge[i].f && dis[v=edge[i].to]==-1)
    	    {
    		dis[v]=dis[u]+1;
    		q[++r]=v;
    		if (v==T) return 1;
    	    }
        }
        return 0;
    }
    
    int dfs(int u,int flow,int T)
    {
        if (u==T || flow==0) return flow;
        int ret=0,delta;
        for (int &i=cur[u],v;i;i=edge[i].next)
    	if (edge[i].w-edge[i].f && dis[v=edge[i].to]==dis[u]+1)
    	{
    	    delta=dfs(v,min(edge[i].w-edge[i].f,flow-ret),T);
    	    if (delta)
    	    {
    		edge[i].f+=delta;
    		edge[i^1].f-=delta;
    		ret+=delta;
    		if (ret==flow) break;
    	    }
    	}
        if (ret!=flow) dis[u]=-1;
        return ret;
    }
    
    int dinic(int S,int T)
    {
        int ans=0;
        while (bfs(S,T))
    	ans+=dfs(S,inf,T);
        return ans;
    }
    
    bool solve()
    {
        for (int i=1;i<=n;i++)
    	for (int j=1,x,y;j<=m;j++)
    	{
    	    x=g[i][j].fir;y=g[i][j].sec;
    	    A[i][j]=add(i,n+j,y-x,x);
    	    extra[i]-=x;extra[n+j]+=x;
    	}
        add(t,s,inf,0);
        int ss=t+1,tt=t+2,sum=0;
        for (int i=s;i<=t;i++)
        {
    	if (extra[i]>0) add(ss,i,extra[i],0),sum+=extra[i];
    	if (extra[i]<0) add(i,tt,-extra[i],0);
        }
        int flow=dinic(ss,tt);
        return flow==sum;
    }
    
    int main()
    {
        TT=read();
        while (TT--)
        {
    	n=read();
    	m=read();
    	s=0;
    	t=n+m+1;
    	init();
    	for (int i=1;i<=n;i++) x=read(),add(s,i,0,x),extra[s]-=x,extra[i]+=x;
    	for (int i=1;i<=m;i++) x=read(),add(n+i,t,0,x),extra[n+i]-=x,extra[t]+=x;
    	for (int i=1;i<=n;i++)
    	    for (int j=1;j<=m;j++)
    		g[i][j]=make_pair(0,inf);
    	Q=read();
    	bool flag=1;
    	while (Q--)
    	{
    	    a=read();
    	    b=read();
    	    scanf("%s",c);
    	    x=read();
    	    if (!a && !b)
    	    {
    		for (int i=1;i<=n;i++)
    		    for (int j=1;j<=m;j++)
    			flag&=ADD(i,j,c[0],x);
    	    }
    	    else if (!a)
    		for (int i=1;i<=n;i++)
    		    flag&=ADD(i,b,c[0],x);
    	    else if (!b)
    		for (int i=1;i<=m;i++)
    		    flag&=ADD(a,i,c[0],x);
    	    else flag&=ADD(a,b,c[0],x);
    	}
    	if (!flag || !solve())
    	    puts("IMPOSSIBLE");
    	else
    	{
    	    for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    		    printf("%d%c",edge[A[i][j]].f+edge[A[i][j]].lower," 
    "[j==m]);
    	}
        }
        return 0;
    }
    
  • 相关阅读:
    中间件
    进程的概念
    操作系统必会
    粘包现象及处理方式
    双下方法
    异常处理
    网络编程基础
    osi七层协议
    面向对象初识
    Django 中间件
  • 原文地址:https://www.cnblogs.com/mrha/p/8227678.html
Copyright © 2011-2022 走看看