码迷,mamicode.com
首页 > 其他好文 > 详细

ZOJ3229 Shoot the Bullet

时间:2018-12-11 15:59:21      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:技巧   错误   网络流   sizeof   def   getch   转换   using   ios   

嘟嘟嘟


有源有汇上下界网络流之最大流。


这题建图其实不难,从\(s\)向每一天连容量为\([0, D]\)的边,每一天向对应的女孩连容量为\([L, R]\)的边,每一个女孩向汇点连容量为\([G, INF]\)的边。
然后转换成上下界网络流的图:建立附加源附加汇\(S, T\),计算每一个点的出入度之差后连边。这时候还要从\(t\)\(s\)连一条\([0, INF]\)的边,形成循环流。
然后从\(S\)\(T\)跑一边最大流,如果流满。则说明存在可行流,于是切掉\(t\)\(s\)的边,再从\(s\)\(t\)跑一边最大流。则答案就是第一次\(s\)\(t\)的流加上第二次的流。
求第一次\(s\)\(t\)的流有一个技巧,因为已经连了\(t\)\(s\)的一条边,所以只要取反向边的流量的相反数即可。



然后我因为数组开的过大(才\(5e6\))在zoj上段错误了……

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("") 
#define space putchar(‘ ‘)
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1505;
const int maxe = 1e5 + 5;
inline ll read()
{
  ll ans = 0;
  char ch = getchar(), last = ‘ ‘;
  while(!isdigit(ch)) last = ch, ch = getchar();
  while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - ‘0‘, ch = getchar();
  if(last == ‘-‘) ans = -ans;
  return ans;
}
inline void write(ll x)
{
  if(x < 0) x = -x, putchar(‘-‘);
  if(x >= 10) write(x / 10);
  putchar(x % 10 + ‘0‘);
}

int n, m, s, t, S, T;

struct Edge
{
  int nxt, from, to, cap, flow;
}e[maxe];
int head[maxn], ecnt = -1;
void addEdge(int x, int y, int w)
{
  e[++ecnt] = (Edge){head[x], x, y, w, 0};
  head[x] = ecnt;
  e[++ecnt] = (Edge){head[y], y, x, 0, 0};
  head[y] = ecnt;
}

int dis[maxn];
bool bfs(int s, int t)
{
  Mem(dis, 0); dis[s] = 1;
  queue<int> q; q.push(s);
  while(!q.empty())
    {
      int now = q.front(); q.pop();
      for(int i = head[now], v; i != -1; i = e[i].nxt)
    {
      if(!dis[v = e[i].to] && e[i].cap > e[i].flow)
        {
          dis[v] = dis[now] + 1;
          q.push(v);
        }
    }
    }
  return dis[t];
}
int cur[maxn];
int dfs(int now, int _t, int res)
{
  if(now == _t || res == 0) return res;
  int flow = 0, f;
  for(int& i = cur[now], v; i != -1; i = e[i].nxt)
    {
      if(dis[v = e[i].to] == dis[now] + 1 && (f = dfs(v, _t, min(res, e[i].cap - e[i].flow))) > 0)
    {
      e[i].flow += f; e[i ^ 1].flow -= f;
      flow += f; res -= f;
      if(res == 0) break;
    }
    }
  return flow;
}

int maxflow(int s, int t)
{
  int flow = 0;
  while(bfs(s, t))
    {
      memcpy(cur, head, sizeof(head));
      flow += dfs(s, t, INF);
    }
  return flow;
}

int b[maxn][maxn], d[maxn];
void init()
{
  Mem(head, -1); ecnt = -1;
  Mem(d, 0); Mem(b, 0);
  s = 0, t = n + m + 1;
  S = t + 1; T = S + 1;
}

int st[maxn];
void print()
{
  for(int i = 1; i <= n; ++i)
    {
      int top = 0;
      for(int j = head[i], v; j != -1; j = e[j].nxt)
    {
      v = e[j].to;
      if(v > n && v <= n + m)  //别忘了前向星是倒着存边
        st[++top] = e[j].flow + b[i][v - n];
    }
      while(top) write(st[top]), enter, top--;
    }
}

int main()
{
  while(~scanf("%d%d", &n, &m))
    {
      init();
      for(int i = 1; i <= m; ++i)
    {
      int x = read();
      addEdge(i + n, t, INF - x);
      d[i + n] += x; d[t] -= x;
    }
      for(int i = 1; i <= n; ++i)
    {
      int C = read(), D = read();
      addEdge(s, i, D);
      //d[s] += D; d[i] -= D;  //最小流量为0,所以不加
      for(int j = 1; j <= C; ++j)
        {
          int id = read() + 1, L = read(), R = read();
          b[i][id] = L;
          addEdge(i, id + n, R - L);
          d[i] += L; d[id + n] -= L;
        }
    }
      int tot = 0;
      for(int i = 0; i <= t; ++i)
    if(d[i] < 0) addEdge(S, i, -d[i]);
    else addEdge(i, T, d[i]), tot += d[i];
      addEdge(t, s, INF);
      if(maxflow(S, T) < tot) {puts("-1\n"); continue;}
      int tp = -e[ecnt].flow; e[ecnt].flow = e[ecnt].cap; // 相当于删去
      write(tp + maxflow(s, t)), enter;
      print(); enter;
    }
  return 0;
}

ZOJ3229 Shoot the Bullet

标签:技巧   错误   网络流   sizeof   def   getch   转换   using   ios   

原文地址:https://www.cnblogs.com/mrclr/p/10102050.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!