zoukankan      html  css  js  c++  java
  • POJ 2396 Budget ——有上下界的网络流

    给定矩阵的每行每列的和,和一些大于小于等于的限制。然后需要求出一组可行解。

    上下界网络流。

    大概的思想就是计算出每一个点他需要强行流入或者流出的量,然后建出超级源点和汇点,然后删除下界,就可以判断是否可行。

    然后把新的上界作为限制,在原图中跑一边。

    然后就是必须的+原图中的进行计算。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    int up[205][205],down[205][205],tt,n,m,row[205];
    #define inf 0x3f3f3f3f
    #define maxn 50005
    int ttt,clu[205],S=maxn-4,T=maxn-3,SS=maxn-2,TT=maxn-1;
    int fr[maxn],h[maxn],to[maxn],ne[maxn],fl[maxn],en=0,ans,a[205][205];
    int du[maxn],id[205][205],tot,Sum,s,t,ban[maxn],SSum,SSSum;
    
    void add(int a,int b,int c)
    {
    	fr[en]=a;to[en]=b;ne[en]=h[a];fl[en]=c;h[a]=en++;
    	fr[en]=b;to[en]=a;ne[en]=h[b];fl[en]=0;h[b]=en++;
    }
    
    int dis[maxn];
    queue<int>q;
    
    bool tell()
    {
    	memset(dis,-1,sizeof dis); dis[s]=0; q.push(s);
    	while (!q.empty())
    	{
    		int x=q.front();q.pop();
    		for (int i=h[x];i>=0;i=ne[i])
    		if (dis[to[i]]==-1&&fl[i]>0&&!ban[i])
    			dis[to[i]]=dis[x]+1,q.push(to[i]);
    	}
    	return dis[t]!=-1;
    }
    
    int zeng(int k,int now)
    {
    	int ret=0;
    	if (k==t) return now;
    	for (int i=h[k];i>=0&&now>ret;i=ne[i])
    	if (dis[to[i]]==dis[k]+1&&fl[i]&&!ban[i]){
    		int tmp=zeng(to[i],min(fl[i],now-ret));
    		fl[i]-=tmp; fl[i^1]+=tmp; ret+=tmp;
    	}
    	if (!ret) dis[k]=-1;
    	return ret;
    }
    
    int dinic(int S,int T)
    {
    	int ret=0,tmp=0;//printf("dinic %d %d
    ",S,T);
    	s=S;t=T;
    	while (tell()) while (tmp=zeng(s,inf)) ret+=tmp;
    	return ret;
    }
    
    void build()
    {
    	en=0;memset(h,-1,sizeof h);memset(a,0,sizeof a);
    	memset(du,0,sizeof du);
    	memset(ban,0,sizeof ban);Sum=0;
    	tot=0;
    	F(i,1,n) F(j,1,m)
    	{
    		if (up[i][j]<down[i][j]) {ans=0;return;}
    		du[i]-=down[i][j];
    		du[j+n]+=down[i][j];
    		up[i][j]-=down[i][j];
    		a[i][j]+=down[i][j];
    		add(i,j+n,up[i][j]);
    	}
    	F(i,1,n) add(S,i,row[i]);
    	F(j,n+1,n+m) add(j,T,clu[j-n]);
    	add(T,S,inf);
    	F(i,1,n+m)
    	{
    		if (du[i]>0) add(SS,i,du[i]),Sum+=du[i];
    		else if (du[i]<0) add(i,TT,-du[i]);
    	}
    	if (dinic(SS,TT)!=Sum) {ans=0;return;}
    	else
    	{
    		ban[en-1]=1;ban[en-2]=1;
    		for (int i=h[SS];i>=0;i=ne[i]) ban[i]=ban[i^1]=1;
    		for (int i=h[TT];i>=0;i=ne[i]) ban[i]=ban[i^1]=1;
    		if (dinic(S,T)!=SSum) {ans=0;return;}
    		F(i,1,n)
    		{
    			for (int j=h[i];j>=0;j=ne[j])
    				a[i][to[j]-n]+=fl[j^1];
    		}
    		ans=1; return;
    	}
    }
    
    int main()
    {
    	scanf("%d",&tt);
    	while (tt--)
    	{
    		memset(down,0,sizeof down);
    		memset(up,0x3f,sizeof up);
    		scanf("%d%d",&n,&m);SSum=SSSum=0;
    		F(i,1,n) scanf("%d",&row[i]),SSum+=row[i];
    		F(i,1,m) scanf("%d",&clu[i]),SSSum+=clu[i];
    		scanf("%d",&ttt);
    		F(i,1,ttt)
    		{
    			int x,y,z;char s[11];
    			scanf("%d%d%s%d",&x,&y,s,&z);
    			switch(s[0])
    			{
    				case '>':
    					if (!x) F(i,1,n)
    					{
    						if (!y) F(j,1,m)
    							down[i][j]=max(down[i][j],z+1);
    						else
    							down[i][y]=max(down[i][y],z+1);
    					}
    					else
    					{
    						if (!y) F(j,1,m)
    							down[x][j]=max(down[x][j],z+1);
    						else
    							down[x][y]=max(down[x][y],z+1);
    					}
    				break;
    				case '=':
    					if (!x) F(i,1,n)
    					{
    						if (!y) F(j,1,m)
    						{
    							up[i][j]=min(up[i][j],z);
    							down[i][j]=max(down[i][j],z);
    						}
    						else
    						{
    							up[i][y]=min(up[i][y],z);
    							down[i][y]=max(down[i][y],z);
    						}
    					}
    					else
    					{
    						if (!y) F(j,1,m)
    						{
    							up[x][j]=min(up[x][j],z);
    							down[x][j]=max(down[x][j],z);
    						}
    						else
    						{
    							up[x][y]=min(up[x][y],z);
    							down[x][y]=max(down[x][y],z);
    						}
    					}
    				break;
    				case '<':
    					if (!x) F(i,1,n)
    					{
    						if (!y) F(j,1,m)
    							up[i][j]=min(up[i][j],z-1);
    						else
    							up[i][y]=min(up[i][y],z-1);
    					}
    					else
    					{
    						if (!y) F(j,1,m)
    							up[x][j]=min(up[x][j],z-1);
    						else
    							up[x][y]=min(up[x][y],z-1);
    					}
    				break;
    			}
    		}
    		build();
    		if ((!ans)||(SSum!=SSSum)) printf("IMPOSSIBLE
    ");
    		else
    		{
    			F(i,1,n) F(j,1,m)
    				printf("%d%c",a[i][j],j==m?'
    ':' ');
    		}
    		if (tt!=0)
    		printf("
    ");
    	}
    }
    

      

  • 相关阅读:
    读《大数据的互联网思维》有感
    IDEA控制台问题:At least one JAR was scanned for TLDs yet contained no TLD
    youDao
    IDEA学习——模板及其常用模板
    IDEA控制台问题:java lang OutOfMemoryError:PermGen space
    MySQL版本的相关问题:com.mysql.cj.jdbc.Driver和com.mysql.jdbc.Driver
    代码自省(周一)
    IDEA链接mySQL问题 : You have an error in your SQL syntax : 'OPTION SQL_SELECT_LIMIT=1000' (or 'OPTION SQL_SELECT_LIMIT=DEFAULT')
    我的大学流水日记
    mysql的使用
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6647436.html
Copyright © 2011-2022 走看看