山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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,inf),使得t的流出量与s的流入量保持相等,即等价于s为源点而t为汇点。

    最后由S->T跑最大流。

 

【代码】

 

  1 #include<set>
  2 #include<cmath>
  3 #include<queue>
  4 #include<vector>
  5 #include<cstdio>
  6 #include<cstring>
  7 #include<iostream>
  8 #include<algorithm>
  9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 11 using namespace std;
 12 
 13 typedef long long ll;
 14 const int N = 4e2+10;
 15 const int M = N*N+10;
 16 const int inf = 1e9;
 17 
 18 ll read() {
 19     char c=getchar();
 20     ll f=1,x=0;
 21     while(!isdigit(c)) {
 22         if(c=='-') f=-1; c=getchar();
 23     }
 24     while(isdigit(c))
 25         x=x*10+c-'0',c=getchar();
 26     return x*f;
 27 }
 28 
 29 struct Edge {
 30     int u,v,cap,flow;
 31     Edge(int u=0,int v=0,int cap=0,int flow=0)
 32         :u(u),v(v),cap(cap),flow(flow){}
 33 };
 34 struct Dinic {
 35     int n,m,s,t;
 36     int d[N],cur[N],vis[N];
 37     vector<int> g[N];
 38     vector<Edge> es;
 39     queue<int> q;
 40     void init(int n) {
 41         this->n=n;
 42         es.clear();
 43         FOR(i,0,n) g[i].clear();
 44     }
 45     void clear() {
 46         FOR(i,0,(int)es.size()-1) es[i].flow=0;
 47     }
 48     void AddEdge(int u,int v,int w) {
 49         es.push_back(Edge(u,v,w,0));
 50         es.push_back(Edge(v,u,0,0));
 51         m=es.size();
 52         g[u].push_back(m-2);
 53         g[v].push_back(m-1);
 54     }
 55     int bfs() {
 56         memset(vis,0,sizeof(vis));
 57         q.push(s); d[s]=0; vis[s]=1;
 58         while(!q.empty()) {
 59             int u=q.front(); q.pop();
 60             FOR(i,0,(int)g[u].size()-1) {
 61                 Edge& e=es[g[u][i]];
 62                 int v=e.v;
 63                 if(!vis[v]&&e.cap>e.flow) {
 64                     vis[v]=1;
 65                     d[v]=d[u]+1;
 66                     q.push(v);
 67                 }
 68             }
 69         }
 70         return vis[t];
 71     }
 72     int dfs(int u,int a) {
 73         if(u==t||!a) return a;
 74         int flow=0,f;
 75         for(int& i=cur[u];i<g[u].size();i++) {
 76             Edge& e=es[g[u][i]];
 77             int v=e.v;
 78             if(d[v]==d[u]+1&&(f=dfs(v,min(a,e.cap-e.flow)))>0) {
 79                 e.flow+=f; 
 80                 es[g[u][i]^1].flow-=f;
 81                 flow+=f; a-=f;
 82                 if(!a) break;
 83             }
 84         }
 85         return flow;
 86     }
 87     int MaxFlow(int s,int t) {
 88         this->s=s,this->t=t;
 89         int flow=0;
 90         while(bfs()) {
 91             memset(cur,0,sizeof(cur));
 92             flow+=dfs(s,inf);
 93         }
 94         return flow;
 95     }
 96 } dc;
 97 
 98 int n,m,flag;
 99 int in[N],up[N][N],down[N][N];
100 
101 void can(int x,int y,int v) {
102     if(v<down[x][y]||v>up[x][y]) flag=1;
103 }
104 
105 int main()
106 {
107     int kase=read();
108     while(kase--) 
109     {
110         memset(in,0,sizeof(in));
111         n=read(),m=read();
112         flag=0;
113         int x,s=n+m+1,t=s+1,S=t+1,T=S+1;
114         dc.init(n+m+5);
115         FOR(i,1,n) {
116             x=read(); in[s]-=x,in[i]+=x;
117             dc.AddEdge(s,i,0);
118         }
119         FOR(i,1,m) {
120             x=read(); in[n+i]-=x,in[t]+=x;
121             dc.AddEdge(i+n,t,0);
122         }
123         int K=read();
124         FOR(i,1,n+m+5) FOR(j,1,n+m+5)
125             up[i][j]=1000,down[i][j]=-1000;
126         while(K--) {
127             char s[2];
128             int x=read(),y=read(),z;
129             scanf("%s",s); z=read();
130             if(x==0 && y) {
131                 FOR(i,1,n) {
132                     if(s[0]=='=') can(i,y+n,z),up[i][y+n]=down[i][y+n]=z;
133                     if(s[0]=='<') up[i][y+n]=min(up[i][y+n],z-1);
134                     if(s[0]=='>') down[i][y+n]=max(down[i][y+n],z+1);
135                 }
136             } else
137             if(x && y==0) {
138                 FOR(i,1,m) {
139                     if(s[0]=='=') can(x,i+n,z),up[x][i+n]=down[x][i+n]=z;
140                     if(s[0]=='<') up[x][i+n]=min(up[x][i+n],z-1);
141                     if(s[0]=='>') down[x][i+n]=max(down[x][i+n],z+1);
142                 }
143             } else
144             if(x==0 && y==0) {
145                 FOR(i,1,n) FOR(j,1,m) {
146                     if(s[0]=='=') can(i,j+n,z),up[i][j+n]=down[i][j+n]=z;
147                     if(s[0]=='<') up[i][j+n]=min(up[i][j+n],z-1);
148                     if(s[0]=='>') down[i][j+n]=max(down[i][j+n],z+1);
149                 }
150             } else {
151                 if(s[0]=='=') can(x,y+n,z),up[x][y+n]=down[x][y+n]=z;
152                 if(s[0]=='<') up[x][y+n]=min(up[x][y+n],z-1);
153                 if(s[0]=='>') down[x][y+n]=max(down[x][y+n],z+1);
154             }
155         }
156         int cur=dc.es.size();
157         FOR(i,1,n) FOR(j,1,m) {
158             if(up[i][j+n]<down[i][j+n]) flag=1;
159             dc.AddEdge(i,j+n,up[i][j+n]-down[i][j+n]);
160             in[i]-=down[i][j+n];
161             in[j+n]+=down[i][j+n];
162         }
163         dc.AddEdge(t,s,inf);
164         if(flag) { puts("IMPOSSIBLE"); continue; }
165         int sum=0;
166         FOR(i,1,t) {
167             if(in[i]>0) dc.AddEdge(S,i,in[i]),sum+=in[i];
168             if(in[i]<0) dc.AddEdge(i,T,-in[i]);
169         }
170         if(sum!=dc.MaxFlow(S,T)) { puts("IMPOSSIBLE"); continue; }
171         else {
172             FOR(i,1,n) FOR(j,1,m) {
173                 printf("%d",dc.es[cur].flow+down[i][j+n]);
174                 if(j!=m) putchar(' '); else puts("");
175                 cur+=2;
176             }
177         }
178     }
179     return 0;
180 }

 

posted on 2016-03-24 11:45  hahalidaxin  阅读(941)  评论(1编辑  收藏  举报