poj 2396 budget

原题:http://poj.org/problem?id=2396

题目大意:
现在有一个M*N的矩阵。已知M行每行的和a[1]..a[m],N列每列的和b[1]..b[n],以及一些限制条件:
第i行j列必须是k;第i行j列必须大于(小于)k。
试给出一种方案。


 建好图,就是一个上下界流!详情 讯代码

#include<stdio.h>
#include<string.h>
#define ROW 205
#define COL 25
#define MAXE 100005
#define MAXN  1250
#define INF 0x7fffffff
int row[ROW],col[COL];
int map[ROW][COL][2];
struct Edge{
	int flow;
	int node;
	int next;
}edge[MAXE];
struct Contain
{
	int a,b,c;
	char ch;
}con[1005];
int cnt,head[MAXN],dep[300],ps[MAXN],ans[ROW][COL];
void add( int a, int b, int flow )
{

	edge[cnt].flow=flow,edge[cnt].node=b,edge[cnt].next=head[a];head[a]=cnt++;
	edge[cnt].flow=0,edge[cnt].node=a,edge[cnt].next=head[b];head[b]=cnt++;

}
int fun(int x, int y, int low, int high)
{
	map[x][y][0] = (map[x][y][0]>low)?map[x][y][0]:low;
	map[x][y][1] = (map[x][y][1]<high)?map[x][y][1]:high;
	return map[x][y][0]<=map[x][y][1];
}
int flow(int s,int t)
{
    int tr,res=0;
    int i,j,k,f,r,top;
    while(1){
        memset(dep,-1,sizeof(dep));
        for(f=dep[ps[0]=s]=0,r=1;f!=r;)
        {
            for(i=ps[f++],j=head[i];j!=-1;j=edge[j].next)
            {
                if(edge[j].flow&&-1==dep[k=edge[j].node]){
                    dep[k]=dep[i]+1;ps[r++]=k;
                    if(k==t){
                        f=r;
                        break;
                    }
                }
            }
        }
        if(dep[t]==-1)break;
        for(i=s,top=0;;)
        {
            if(i==t)
            {
                for(k=0,tr=INF;k<top;++k)
				{
                    if(edge[ps[k]].flow<tr)tr=edge[ps[f=k]].flow;
				}
                    for(k=0;k<top;++k)
                        edge[ps[k]].flow-=tr,edge[ps[k]^1].flow+=tr;
                    res+=tr;i=edge[ps[top=f]^1].node;
            }
            for(j=head[i];j!=-1;j=edge[j].next)
			{
                if(edge[j].flow&&dep[i]+1==dep[edge[j].node])break;
			}
				if(j!=-1)
				{
					ps[top++]=j;
					i=edge[j].node;
				}
				else
				{
					if(!top)break;
					dep[i]=-1;i=edge[ps[--top]^1].node;
				}
        }
    }
    return res;
}
int main()
{
	int T;
	int n,m,N;
	int i,j,k,a,b,mark;
	int s,t,sum,sum1,sum2;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		sum1 = sum2 = 0;
		for(i=1;i<=n;i++){
			scanf("%d",&row[i]);
			sum1+=row[i];
		}
		for( i = 1; i <= m; i++ )
		{
			scanf("%d",&col[i]);
			sum2+=col[i];
		}
		
		for( i = 1; i <= n; i++ )
		{
			for( j = 1; j <= m; j++ )
				map[i][j][0] = 0, map[i][j][1] = (row[i] < col[j])?row[i]:col[j];
		}
		scanf("%d",&N);
		for( i = 1; i <= N; i++ )
			scanf("%d %d %c %d",&con[i].a,&con[i].b,&con[i].ch,&con[i].c);
		mark=1;
		for( mark = i = 1; (i <= N)&&mark; i++ )
		{
			a = con[i].a;  b = con[i].b;
			if(a&&b)
			{
						if(con[i].ch == '=')
						{ 
							if(!fun( a, b, con[i].c, con[i].c ))
							{
								mark = 0; 
								continue;
							}
						}
						else if(con[i].ch == '>') 
						{
							if(!fun( a, b, con[i].c + 1, INF ))
							{
								mark = 0; 
								continue;
							}
						}
						else
						{
							if(!fun( a, b, 0, con[i].c - 1 ))
							{
								mark = 0;
								continue;
							}
						}
			}
			else if(a||b)
			{
				if(a){
					for(j = 1; (j <= m)&&mark; j++)
					{
						b=j;
						if(con[i].ch == '=')
						{ 
							if(!fun( a, b, con[i].c, con[i].c ))
							{
								mark = 0; 
								continue;
							}
						}
						else if(con[i].ch == '>') 
						{
							if(!fun( a, b, con[i].c + 1, INF ))
							{
								mark = 0; 
								continue;
							}
						}
						else
						{
							if(!fun( a, b, 0, con[i].c - 1 ))
							{
								mark = 0;
								continue;
							}
						}
					}
				}
				else
				{
					for(j = 1; (j <= n)&&mark; j++)
					{
						a=j;
						if(con[i].ch == '=')
						{ 
							if(!fun( a, b, con[i].c, con[i].c ))
							{
								mark = 0; 
								continue;
							}
						}
						else if(con[i].ch == '>') 
						{
							if(!fun( a, b, con[i].c + 1, INF ))
							{
								mark = 0; 
								continue;
							}
						}
						else
						{
							if(!fun( a, b, 0, con[i].c - 1 ))
							{
								mark = 0;
								continue;
							}
						}
					}
				}
			}
			else
			{
				for(j = 1; (j <= n)&&mark; j++)
					for(k = 1; (k <= m)&&mark; k++)
					{
						a=j,b=k;
						if(con[i].ch == '=')
						{ 
							if(!fun( a, b, con[i].c, con[i].c ))
							{
								mark = 0; 
								continue;
							}
						}
						else if(con[i].ch == '>') 
						{
							if(!fun( a, b, con[i].c + 1, INF ))
							{
								mark = 0; 
								continue;
							}
						}
						else
						{
							if(!fun( a, b, 0, con[i].c - 1 ))
							{
								mark = 0;
								continue;
							}
						}
					}
			}
		}

		if( mark && (sum1 == sum2) )
		{
			memset(head,-1,sizeof(head));
			cnt = 0;
			sum = 0;
			s =  n + m + 2, t = n + m + 3;
			for(j = 1; j <= n; j++)
			{
				add( 0, j, 0);
				add( 0, t, row[j] );
				add( s, j, row[j] );
				sum += row[j];
			}
			sum1 = s - 1;
			for(j = 1; j <= m; j++)
			{
				add( j+n, sum1, 0);
				add( j+n, t, col[j] );
				add( s, sum1, col[j] );
				sum += col[j];
			}
			
			
			for(j = 1; j <= n; j++)
			{
				for(k = 1; k <= m; k++)
				{
					add( j, n+k, map[j][k][1]-map[j][k][0] );
					add( j, t, map[j][k][0] );
					add( s, n+k, map[j][k][0]  );
					sum+=map[j][k][0];
				}
			}

			add( s-1, 0, INF );
			if(sum==flow(s,t))
			{
				a=n+1,b=n+k;
				for(j = 1; j <= n; j++)
				{
					for(k = head[j]; ~k ; k = edge[k].next)
					{
						if((edge[k].node>=a)&&(edge[k].node<=b))
							ans[j][edge[k].node-n]=map[j][edge[k].node-n][0]+edge[k^1].flow;
					}
				}
				for(j = 1; j <= n; j++)
				{
					for(k = 1; k <= m; k++)
						printf("%d ",ans[j][k]);
					printf("\n");
				}
				printf("\n");
				
			}
			else
				printf("IMPOSSIBLE\n\n");
		}
		else
			printf("IMPOSSIBLE\n\n");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值