【POJ 2396 Budget】 有上下界的可行流

题目链接:http://poj.org/problem?id=2396

题目大意:有一个n*m的矩阵,每个位置(i,j)都有一个值,接下来输入n个数,每个数代表矩阵对应行的和,接下来输入m个数,每个数代表对应列的和。接下来有Q个操作,每个操作输入i j c val。(注意i==0||j==0的特判。这里不说明了)

1、当c为'>': 表示第i行j列的数值要大于val。(实际下级要设为val+1)

2、当c为'<': 表示第i行j列的数值要小于val。(实际上界要设为val-1)

3、当c为'=': 表示第i行j列的数值要等于val。

让你求是否存在满足要求的矩阵,有则输出对应的矩阵,无则输出”impossible”。

解题思路:其实这样的题吧,关键还是想到构图,想到了就是一水,没想到就是一难。 

              增设一源点s和一汇点d,源点s和每行的代表虚拟节点row[i]相连,权值为该行的权值总和,每列的代表虚拟节点和汇点d相连,权值为该列的权值总和,行连接列代表节点(i,j)即i行j列,它的容量上下界根据题目来确定。

            连接一条附加边(d,s)容量为无穷,剩下的操作和无源汇有上下界的可行流一样。

            这题让我蛋疼了许久,让我又悲又喜,悲的是明显各种测试各种对就是TLE(最后我还猥琐的去官方下载数据),喜的是这题让我找到了我的Dinic模板的一个bug,就是这个bug才让我的Dinic跑慢了许多,唉,前面写了那么多题都没测试出来,弱爆了。 

View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 const int mn=5555;
  9 const int mm=100000;
 10 const int oo=0x3fffffff;
 11 int node, st, sd, edge;
 12 int reach[mm], flow[mm], next[mm];
 13 int head[mn], work[mn], dis[mn], que[mn];
 14 int low[225][225], up[225][225], du[mn], ans[225][225];
 15 bool flag;
 16 
 17 inline void init(int _node, int _st, int _sd)
 18 {
 19     node=_node, st=_st, sd=_sd;
 20     for(int i=0; i<node; i++)
 21         head[i]=-1, du[i]=0;
 22     edge=0;
 23 }
 24 
 25 void addedge(int u, int v, int c1, int c2)
 26 {
 27     reach[edge]=v, flow[edge]=c1, next[edge]=head[u], head[u]=edge++;
 28     reach[edge]=u, flow[edge]=c2, next[edge]=head[v], head[v]=edge++;
 29 }
 30 
 31 bool bfs()
 32 {
 33     int u, v, l=0, h=0;
 34     for(int i=0; i<node; i++) dis[i]=-1;
 35     dis[st]=0;
 36     que[l++]=st;
 37     while(l!=h)
 38     {
 39         u=que[h++];
 40         if(h==mn) h=0;
 41         for(int i=head[u]; i>=0; i=next[i])
 42         {
 43             v=reach[i];
 44             if(flow[i]>0&&dis[v]<0)  ///!!题目中可能边权有为负的边,TLE到死
 45             {
 46                 dis[v]=dis[u]+1;
 47                 que[l++]=v;
 48                 if(l==mn) l=0;
 49                 if(v==sd) return true;
 50             }
 51         }
 52     }
 53     return false;
 54 }
 55 
 56 int dfs(int u, int exp)
 57 {
 58     if(sd==u) return exp;
 59     for(int &i=work[u]; i>=0; i=next[i])
 60     {
 61         int v=reach[i], tmp;
 62         if(flow[i]>0&&dis[v]==dis[u]+1&&(tmp=dfs(v,min(flow[i],exp)))>0)
 63         {
 64             flow[i]-=tmp;
 65             flow[i^1]+=tmp;
 66             return tmp;
 67         }
 68     }
 69     return 0;
 70 }
 71 
 72 int Dinic()
 73 {
 74     int max_flow=0, flow;
 75     while(bfs())
 76     {
 77         for(int i=0; i<node; i++) work[i]=head[i];
 78         while(flow=dfs(st,oo)) max_flow+=flow;
 79     }
 80     return max_flow;
 81 }
 82 
 83 void change(int u, int v,int a, int b)
 84 {
 85     low[u][v]=max(low[u][v],a);
 86     up[u][v]=min(up[u][v],b);
 87     if(low[u][v]>up[u][v]) flag=1;
 88 }
 89 
 90 int main()
 91 {
 92     int g, n, m, T, Q, tcase=0;
 93     cin >> T;
 94     while(T--)
 95     {
 96         int aa=0, bb=0;
 97         scanf("%d%d",&n,&m);
 98         init(n+m+2,0,n+m+1);
 99         for(int i=1; i<=n; i++)
100         {
101             scanf("%d",&g);
102             aa+=g;
103             du[st]-=g;
104             du[i]+=g;
105         }
106         for(int i=1; i<=m; i++)
107         {
108             scanf("%d",&g);
109             bb+=g;
110             du[i+n]-=g;
111             du[sd]+=g;
112         }
113         for(int i=1; i<225; i++)
114             for(int j=1; j<225; j++)
115             {
116                 low[i][j]=0;
117                 up[i][j]=oo;
118             }
119         cin >> Q;
120         int u, v, c, flag=0;
121         char ch[5];
122         while(Q--)
123         {
124             scanf("%d%d%s%d",&u,&v,ch,&c);
125             if(u==0&&v==0)
126             {
127                 for(int i=1; i<=n; i++)
128                     for(int j=1; j<=m; j++)
129                     {
130                         if(ch[0]=='>') change(i,j+n,c+1,up[i][j+n]);
131                         else if(ch[0]=='<') change(i,j+n,low[i][j+n],c-1);
132                         else change(i,j+n,c,c);
133                     }
134             }
135             else if(u==0)
136             {
137                 for(int i=1; i<=n; i++)
138                 {
139                     if(ch[0]=='>') change(i,v+n,c+1,up[i][v+n]);
140                     else if(ch[0]=='<') change(i,v+n,low[i][v+n],c-1);
141                     else change(i,v+n,c,c);
142                 }
143             }
144             else if(v==0)
145             {
146                 for(int j=1; j<=m; j++)
147                 {
148                     if(ch[0]=='>') change(u,j+n,c+1,up[u][j+n]);
149                     else if(ch[0]=='<') change(u,j+n,low[u][j+n],c-1);
150                     else change(u,j+n,c,c);
151                 }
152             }
153             else
154             {
155                 if(ch[0]=='>') change(u,v+n,c+1,up[u][v+n]);
156                 else if(ch[0]=='<') change(u,v+n,low[u][v+n],c-1);
157                 else change(u,v+n,c,c);
158             }
159         }
160         if(tcase) puts("");
161         tcase=1;
162         if(flag||aa!=bb) puts("IMPOSSIBLE");
163         else
164         {
165             addedge(sd,st,oo,0);
166             for(int i=1; i<=n; i++)
167                 for(int j=1; j<=m; j++)
168                 {
169                     du[i]-=low[i][j+n];
170                     du[j+n]+=low[i][j+n];
171                     addedge(i,j+n,up[i][j+n]-low[i][j+n],0);
172                 }
173             st=node, sd=node+1, node+=2;
174             head[st]=head[sd]=-1;
175             int flowmax, sum=0;
176             for(int i=0; i<node-2; i++)
177             {
178                 if(du[i]>0) sum+=du[i], addedge(st,i,du[i],0);
179                 if(du[i]<0) addedge(i,sd,-du[i],0);
180             }
181             flowmax=Dinic();
182             if(flowmax!=sum) puts("IMPOSSIBLE");
183             else
184             {
185                 for(int i=1; i<=n; i++)
186                     for(int j=head[i]; j>=0; j=next[j])
187                         ans[i][reach[j]]=flow[j^1]+low[i][reach[j]];
188                 for(int i=1; i<=n; i++)
189                     for(int j=1; j<=m; j++)
190                     {
191                         if(j!=m) printf("%d ",ans[i][j+n]);
192                         else printf("%d\n",ans[i][j+n]);
193                     }
194             }
195         }
196     }
197     return 0;
198 }

 

 

 

posted @ 2013-04-06 10:33  Mr. Ant  阅读(650)  评论(0编辑  收藏  举报