zoukankan      html  css  js  c++  java
  • 【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 }
  • 相关阅读:
    javascript 调试代码
    简洁的js拖拽代码
    搭个小窝
    FastDFS随笔
    JDK6和JDK7中String的substring()方法及其差异
    杂笔
    JVM内存随笔
    java中的final和volatile详解
    关于java的Synchronized,你可能需要知道这些(下)
    关于java的Synchronized,你可能需要知道这些(上)
  • 原文地址:https://www.cnblogs.com/kane0526/p/3001091.html
Copyright © 2011-2022 走看看