1. 程式人生 > >POJ2396 Budget

POJ2396 Budget

n) 轉換 else 簡潔 += 無限 head %s tchar

傳送門

這題是真的惡心……

有源匯的上下界網絡流求可行流……

首先矩陣的建圖基本比較清晰,就是行列之間連邊,其上下界由給定的條件決定。這題其實有兩種改造法都能過。第一種是最正統的套路,就是首先建立原點和匯點,然後把行向原點連邊,容量全都是0(因為上下界的差值是0),不過要更改這些點的流入和流出下限,中間的邊還是按上界減去下界為容量。這樣我們現在形成了一個有源匯的上下界網絡流,只要加上一條從匯點到原點容量為INF的一條邊,它就成了一個無源匯的上下界網絡流。然後建立輔助源匯點跑流即可。

第二種比較簡潔,就是不建立源匯點,只把矩陣行列之間的邊構造出來之後,直接建立輔助源匯點跑流。這樣其實也是正確的,為啥呢……因為其實第一種和第二種的不同在於,他多了源匯點……但是因為源匯點直接為了轉換為無源匯的圖,又加上了一條INF的邊,這樣的話流就可以無限的從這裏跑了……所以第一種多出來的流最後也沒有用上……(以上都是感性理解orz……其實我也不能詳細證明為啥都行)

然後就這麽建圖這題就可以過了。但是這題的建圖是真的惡心……尤其是如果你沒有使用鄰接矩陣存流的下屆……我是用下標計算處理的……debug到痛不欲生……看一下兩種代碼吧。

第一種:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar(‘\n‘)
#define fr friend inline
#define y1 poj
#define mp make_pair
#define pr pair<int,int>
#define fi first
#define sc second
#define pb push_back

using namespace std;
typedef long long ll;
const int M = 1000005;
const int N = 505;
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;

int read()
{
   int ans = 0,op = 1;char ch = getchar();
   while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) op = -1;ch = getchar();}
   while(ch >= ‘0‘ && ch <= ‘9‘) ans = ans * 10 + ch - ‘0‘,ch = getchar();
   return ans * op;
}

struct edge
{
   int next,to,from,v;
}e[M<<1];

int Ti,n,m,head[N<<1],ecnt,x,y,a[M<<1],b[M<<1];
int rsum[N<<1],csum[N<<1],S,T,tot,dep[N<<1],cur[N<<1];
int hsum[N<<1],lsum[N<<1],S1,T1,k,z;
queue <int> q;
char s[3];
bool flag;

void add(int x,int y,int z)
{
   e[++ecnt].to = y;
   e[ecnt].from = x;
   e[ecnt].next = head[x];
   e[ecnt].v = z;
   head[x] = ecnt;
}

void build()
{
   x = read(),y = read(),scanf("%s",s),z = read();
   if(s[0] == ‘>‘)
   {
      z++;
      if((z > hsum[x] && x != 0) || (z > lsum[y] && y != 0)) flag = 1;
      if(x == 0 && y == 0) rep(i,1,n*m) a[i] = z;
      else if(x == 0) rep(i,0,n-1) a[i*m+y] = z;
      else if(y == 0) rep(i,1,m) a[(x-1)*m+i] = z;
      else a[(x-1)*m+y] = z;
   }
   if(s[0] == ‘<‘)
   {
      z--;
      if(x == 0 && y == 0) rep(i,1,n*m) b[i] = z;
      else if(x == 0) rep(i,0,n-1) b[i*m+y] = z;
      else if(y == 0) rep(i,1,m) b[(x-1)*m+i] = z;
      else b[(x-1)*m+y] = z;
   }
   if(s[0] == ‘=‘)
   {
      if((z > hsum[x] && x != 0) || (z > lsum[y] && y != 0)) flag = 1;
      if(x == 0 && y == 0) rep(i,1,n*m) a[i] = b[i] = z;
      else if(x == 0) rep(i,0,n-1) a[i*m+y] = b[i*m+y] = z;
      else if(y == 0) rep(i,1,m) a[(x-1)*m+i] = b[(x-1)*m+i] = z;
      else a[(x-1)*m+y] = b[(x-1)*m+y] = z;
   }
}

void rebuild()
{
   rep(i,S,T)
   {
      int now = csum[i] - rsum[i];
      if(now < 0) add(S1,i,-now),add(i,S1,0);
      else add(i,T1,now),add(T1,i,0),tot += now;
   }
}

void clear()
{
   flag = 0;
   memset(head,-1,sizeof(head)),ecnt = -1,tot = 0;
   memset(a,0,sizeof(a)),memset(b,0x3f,sizeof(b));
   rep(i,S,T1) rsum[i] = csum[i] = 0;
}

bool bfs(int s,int t)
{
   while(!q.empty()) q.pop();
   rep(i,0,t) cur[i] = head[i];
   memset(dep,-1,sizeof(dep));
   dep[s] = 0,q.push(s);
   while(!q.empty())
   {
      int k = q.front();q.pop();
      for(int i = head[k];~i;i = e[i].next)
      {
     if(e[i].v && dep[e[i].to] == -1)
        dep[e[i].to] = dep[k] + 1,q.push(e[i].to);
      }
   }
   return dep[t] != -1;
}

int dfs(int s,int t,int lim)
{
   if(s == t || !lim) return lim;
   int flow = 0;
   for(int i = cur[s];~i;i = e[i].next)
   {
      cur[s] = i;
      if(dep[e[i].to] != dep[s] + 1) continue;
      int f = dfs(e[i].to,t,min(lim,e[i].v));
      if(f)
      {
     e[i].v -= f,e[i^1].v += f;
     flow += f,lim -= f;
     if(!lim) break;
      }
   }
   if(!flow) dep[s] = -1;
   return flow;
}

int dinic(int s,int t)
{
   int maxflow = 0;
   while(bfs(s,t)) maxflow += dfs(s,t,INF);
   return maxflow;
}

int main()
{
  //freopen("a.in","r",stdin);
  //freopen("f.out","w",stdout);
   Ti = read();
   while(Ti--)
   {
      n = read(),m = read(),T = n + m + 1,S1 = T + 1,T1 = S1 + 1;
      clear();
      rep(i,1,n) hsum[i] = read();
      rep(i,1,m) lsum[i] = read();
      k = read();
      rep(i,1,k) build();
      rep(i,1,n)
      rep(j,1,m)
      {
      int f = a[(i-1)*m+j],g = b[(i-1)*m+j];
      add(i,j+n,g-f),add(j+n,i,0);
      csum[i] += f,rsum[j+n] += f;
      }
      rep(i,1,n) add(S,i,0),add(i,S,0),csum[S] += hsum[i],rsum[i] += hsum[i];
      rep(i,1,m) add(i+n,T,0),add(T,i+n,0),csum[i+n] += lsum[i],rsum[T] += lsum[i];
      add(T,S,INF),add(S,T,0);
      rebuild();
      int g = dinic(S1,T1);
      if(flag || tot > g) printf("IMPOSSIBLE\n");
      else
      {
     rep(i,1,n)
     {
        rep(j,1,m)
        {
           int g = (i - 1) * m + j - 1;
           printf("%d ",e[g<<1|1].v + a[g+1]);
        }
        enter;
     }
      }
   }
   return 0;
}

第二種:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar(‘\n‘)
#define fr friend inline
#define y1 poj
#define mp make_pair
#define pr pair<int,int>
#define fi first
#define sc second
#define pb push_back

using namespace std;
typedef long long ll;
const int M = 1000005;
const int N = 505;
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;

int read()
{
   int ans = 0,op = 1;char ch = getchar();
   while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) op = -1;ch = getchar();}
   while(ch >= ‘0‘ && ch <= ‘9‘) ans = ans * 10 + ch - ‘0‘,ch = getchar();
   return ans * op;
}

struct edge
{
   int next,to,from,v;
}e[M<<1];

int Ti,n,m,head[N<<1],ecnt,x,y,a[M<<1],b[M<<1];
int rsum[N<<1],csum[N<<1],S,T,tot,dep[N<<1],cur[N<<1];
int hsum[N<<1],lsum[N<<1],S1,T1,k,z;
queue <int> q;
char s[3];
bool flag;

void add(int x,int y,int z)
{
   e[++ecnt].to = y;
   e[ecnt].from = x;
   e[ecnt].next = head[x];
   e[ecnt].v = z;
   head[x] = ecnt;
}

void build()
{
   x = read(),y = read(),scanf("%s",s),z = read();
   if(s[0] == ‘>‘)
   {
      z++;
      if((z > hsum[x] && x != 0) || (z > lsum[y] && y != 0)) flag = 1;
      if(x == 0 && y == 0) rep(i,1,n*m) a[i] = z;
      else if(x == 0) rep(i,0,n-1) a[i*m+y] = z;
      else if(y == 0) rep(i,1,m) a[(x-1)*m+i] = z;
      else a[(x-1)*m+y] = z;
   }
   if(s[0] == ‘<‘)
   {
      z--;
      if(x == 0 && y == 0) rep(i,1,n*m) b[i] = z;
      else if(x == 0) rep(i,0,n-1) b[i*m+y] = z;
      else if(y == 0) rep(i,1,m) b[(x-1)*m+i] = z;
      else b[(x-1)*m+y] = z;
   }
   if(s[0] == ‘=‘)
   {
      if((z > hsum[x] && x != 0) || (z > lsum[y] && y != 0)) flag = 1;
      if(x == 0 && y == 0) rep(i,1,n*m) a[i] = b[i] = z;
      else if(x == 0) rep(i,0,n-1) a[i*m+y] = b[i*m+y] = z;
      else if(y == 0) rep(i,1,m) a[(x-1)*m+i] = b[(x-1)*m+i] = z;
      else a[(x-1)*m+y] = b[(x-1)*m+y] = z;
   }
}

void rebuild()
{
   rep(i,S,T)
   {
      int now = csum[i] - rsum[i];
      //printf("%d %d\n",i,now);
      if(now < 0) add(S1,i,-now),add(i,S1,0);
      else add(i,T1,now),add(T1,i,0),tot += now;
   }
}

void clear()
{
   flag = 0;
   memset(head,-1,sizeof(head)),ecnt = -1,tot = 0;
   memset(a,0,sizeof(a)),memset(b,0x3f,sizeof(b));
   rep(i,S,T1) rsum[i] = csum[i] = 0;
}

bool bfs(int s,int t)
{
   while(!q.empty()) q.pop();
   rep(i,0,t) cur[i] = head[i];
   memset(dep,-1,sizeof(dep));
   dep[s] = 0,q.push(s);
   while(!q.empty())
   {
      int k = q.front();q.pop();
      for(int i = head[k];~i;i = e[i].next)
      {
     if(e[i].v && dep[e[i].to] == -1)
        dep[e[i].to] = dep[k] + 1,q.push(e[i].to);
      }
   }
   return dep[t] != -1;
}

int dfs(int s,int t,int lim)
{
   if(s == t || !lim) return lim;
   int flow = 0;
   for(int i = cur[s];~i;i = e[i].next)
   {
      cur[s] = i;
      if(dep[e[i].to] != dep[s] + 1) continue;
      int f = dfs(e[i].to,t,min(lim,e[i].v));
      if(f)
      {
     e[i].v -= f,e[i^1].v += f;
     flow += f,lim -= f;
     if(!lim) break;
      }
   }
   if(!flow) dep[s] = -1;
   return flow;
}

int dinic(int s,int t)
{
   int maxflow = 0;
   while(bfs(s,t)) maxflow += dfs(s,t,INF);
   return maxflow;
}

int main()
{
  //freopen("a.in","r",stdin);
  //freopen("f.out","w",stdout);
   Ti = read();
   while(Ti--)
   {
      n = read(),m = read(),T = n + m + 1,S1 = T + 1,T1 = S1 + 1;
      clear();
      rep(i,1,n) hsum[i] = read(),rsum[i] += hsum[i];
      rep(i,1,m) lsum[i] = read(),csum[i+n] += lsum[i];
      k = read();
      rep(i,1,k) build();
      rep(i,1,n)
      rep(j,1,m)
      {
      int f = a[(i-1)*m+j],g = b[(i-1)*m+j];
      add(i,j+n,g-f),add(j+n,i,0);
      csum[i] += f,rsum[j+n] += f;
      }
      rebuild();
      int g = dinic(S1,T1);
      if(flag || tot > g) printf("IMPOSSIBLE\n");
      else
      {
     rep(i,1,n)
     {
        rep(j,1,m)
        {
           int g = (i - 1) * m + j - 1;
           printf("%d ",e[g<<1|1].v + a[g+1]);
        }
        enter;
     }
      }
   }
   return 0;
}

POJ2396 Budget