poj 2396 Budget

来源:互联网 发布:防闪退的软件 编辑:程序博客网 时间:2024/06/11 01:56


//POJ 2396  上下界可行流
//引用这位仁兄的解题报告:http://hi.baidu.com/zfy0701/blog/item/6449d82a64e15e3e5343c1ba.html
#include <iostream>
#include <algorithm>

using namespace std;
const int inf=1<<28;
int n,m,s,t,ds,dt;

const int VMAX = 300;
const int EMAX = 50000;

const int null = -1;
struct Edge
{
 int adj,next,re;    //指向的点,下一边的下标,逆边的下标
 int r,f;          //余留网边的容量和流量
 int bot;        //下界
}h[EMAX+10];  //用下标模拟指针构邻接表
int p[VMAX+10],c;
int gap[VMAX+10],pre[VMAX+10],dis[VMAX+10];

int bottom[VMAX+10][VMAX+10],top[VMAX+10][VMAX+10];
//插边,k,l为端点,cap为边容量
void insert(int k,int l,int bot,int top)
{
 h[++c].adj=l;
 h[c].r=top;
 h[c].bot=bot;
 h[c].next=p[k];
 p[k]=c;
 h[c].f=0;
 h[c].re=c+1;  

    //逆边
 h[++c].adj=k;
 h[c].r=h[c].bot=h[c].f=0;
 h[c].next=p[l];
 p[l]=c;
 h[c].re=c-1;    //与上面对应

}
int sap(int s,int t,int N)  //N为点数(包括源汇)
{
 memset(dis,0,sizeof(dis));
 memset(gap,0,sizeof(gap));
 gap[0]=N;
 int u=s,ca=inf,ans=0;
 while (dis[s]<N)
 {
  while (1)
  {
   bool flag=false;
   for (int j=p[u];j!=null;j=h[j].next)
   {
    int i=h[j].adj;
    if (h[j].r && dis[u]==dis[i]+1)
    {
     ca=min(ca,h[j].r);
     pre[i]=j;u=i;  //注意邻接表版的pre表示的是边
     if (i==t)
     {
      ans+=ca;
      while (i!=s)
      {
       u=pre[i];
       int re=h[u].re;
       
       h[u].f+=ca;
       h[re].f=-h[u].f;
       h[u].r-=ca;
       h[re].r+=ca;
       i=h[re].adj;
      }
      u=s;ca=inf;
     }
     flag=true;
     break;
    }
   }
   if (!flag) break;
  }

  int Min=N;
  for (int j=p[u];j!=null;j=h[j].next)
   if (h[j].r && dis[h[j].adj]<Min)
    Min=dis[h[j].adj];
  if (--gap[dis[u]] == 0) break;
  gap[dis[u]=Min+1]++;
  if (u!=s) u=h[h[pre[u]].re].adj;
 }
 
 return ans;
}


void init()
{
 c=-1;
 memset(p,-1,sizeof(p));
}
int in[VMAX+10],out[VMAX+10];
int ind[VMAX+10][VMAX+10];

bool limit(int i,int j,char *op,int val)
{
 if (strcmp(op,"=")==0)
 {
  if (val<bottom[i][j] || top[i][j]!=-1 && val>top[i][j]) return false;
  bottom[i][j]=top[i][j]=val;
 }
 else if (strcmp(op,"<")==0)
 {
  --val;
  if (val<bottom[i][j]) return false;
  if (top[i][j]==-1 || top[i][j]>val) top[i][j]=val;
 }
 else
 {
  ++val;
  if (top[i][j]!=-1 && val>top[i][j]) return false;
  if (val>bottom[i][j]) bottom[i][j]=val;
 }
 return true;
}


int main()
{
 int tmm;
 scanf("%d",&tmm);
 bool first=true;
 while (tmm--)
 {
  if (first) first=false;
  else printf("/n");
  memset(in,0,sizeof(in));
  memset(out,0,sizeof(out));
  scanf("%d%d",&n,&m);
  s=0,t=n+m+1;
  init();
  int a,b,e,count;
  char op[5];
  for (int i=1;i<=n;i++)
  {
   scanf("%d",&a);
   insert(s,i,a,a);
   out[s]+=a;in[i]+=a;
  }
  for (int i=n+1;i<=n+m;i++)
  {
   scanf("%d",&a);
   insert(i,t,a,a);
   out[i]+=a;in[t]+=a;
  }

  memset(bottom,0,sizeof(bottom));
  memset(top,-1,sizeof(top));
  scanf("%d",&count);
  bool flag=true;
  while (count--)
  {
   scanf("%d%d%s%d",&a,&b,op,&e);
   if (!flag) continue;
   if (a==0)
   {
    for (a=1;a<=n;a++)
    {
     if (b==0)
     {
      for (b=1;b<=m;b++) if (!(limit(a,b,op,e))) flag=0;
     }
     else if ( !limit(a,b,op,e) ) flag=0;
    }
   }
   else if (b==0)
   {
    for (b=1;b<=m;b++) if (!limit(a,b,op,e)) flag=0;
   }
   else  if (!limit(a,b,op,e)) flag=0;
   
  }
  if (!flag)
  {
   printf("IMPOSSIBLE/n");
   continue;
  }

  

  for (int i=1;i<=n;i++)
   for (int j=1;j<=m;j++)
   {
    ind[i][j]=c+1;
    insert(i,n+j,bottom[i][j],top[i][j]==-1?inf:top[i][j]);
    in[n+j]+=bottom[i][j];out[i]+=bottom[i][j];
   }
  ds=n+m+2,dt=n+m+3;
  
  //拆边,附加源汇
  for (int i=0;i<=n+m+1;i++)
   for (int j=p[i];j!=null;j=h[j].next)
   {
    h[j].r-=h[j].bot;
   }
  for (int i=0;i<=n+m+1;i++)
  {
   insert(ds,i,0,in[i]);
   insert(i,dt,0,out[i]);
  }
  insert(t,s,0,inf);   //插入边(t,s,0,inf)
  sap(ds,dt,n+m+4);  //求一次最大流
  flag=true;

  for (int i=p[ds];i!=null;i=h[i].next)
  {
   if (h[i].r) { flag= false; break;}
  }

  if (!flag)
  {
   printf("IMPOSSIBLE/n");
   continue;
  }
  
  
  for (int i=1;i<=n;i++)
  {
   for (int j=1;j<=m;j++)
   {
    if (j!=1) printf(" ");
    printf("%d",h[ind[i][j]].f+h[ind[i][j]].bot);
   }
   printf("/n");
  }
 }
 system("pause");
 return 0;
}