poj2396 Budget(有源汇上下界可行流)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于poj2396 Budget(有源汇上下界可行流)的主要内容,如果未能解决你的问题,请参考以下文章