关闭

hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流判断 )

标签: hdu
675人阅读 评论(0) 收藏 举报
分类:

题意:有n个点和m条有向边构成的网络,每条边有两个花费:

d:毁坏这条边的花费 b:重建一条双向边的花费

寻找这样两个点集,使得点集s到点集t满足 毁坏所有S到T的路径的费用和 > 毁坏所有T到S的路径的费用和 + 重建这些T到S的双向路径的费用和。


思路1:


然后这个无源汇带上下界网络流的可行流问题的求解方法见这里~~

建图就是上面说的那样啦~最后判断有没有可行流就是求一下我们所构造的这个新的网络的最大流~然后判断一下这个最大流是否满流~(即判断最大流是否和附加源点的流出总量相等~~)


code:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<cstdlib>
using namespace std;

#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define mem(a, b) memset(a, b, sizeof(a))

typedef pair<int,int> pii;
typedef long long LL;
//------------------------------
const int maxn = 210;

int n,m;

struct Edge{
      int to, cap, rev;//终点 容量 反向边
      Edge(int to_ = 0, int cap_ = 0, int rev_ = 0){
            to = to_;
            cap = cap_;
            rev = rev_;
      }
};
vector<Edge> g[maxn];
int level[maxn];//顶点到源点的距离标号
int iter[maxn];

void add_Edge(int from, int to, int cap){
      Edge tmp1(to, cap, g[to].size());
      g[from].push_back(tmp1);
      Edge tmp2(from, 0, g[from].size()-1);
      g[to].push_back(tmp2);
}
void bfs(int s){
      memset(level, -1, sizeof(level));
      queue<int> q;
      level[s] = 0;
      q.push(s);
      while(!q.empty()){
            int v = q.front();
            q.pop();
            for(int i = 0; i < g[v].size(); i++){
                  Edge& e = g[v][i];
                  if(e.cap > 0 && level[e.to] < 0){
                  level[e.to] = level[v] + 1;
                  q.push(e.to);
                  }
            }
      }
}
int dfs(int v, int t, int f){
      if(v == t) return f;
      for(int& i = iter[v]; i < g[v].size(); i++){
            Edge& e = g[v][i];
            if(e.cap > 0 && level[v] < level[e.to]){
                  int d = dfs(e.to, t, min(e.cap, f));
                  if(d > 0){
                  e.cap -= d;
                  g[e.to][e.rev].cap += d;
                  return d;
                  }
            }

      }
      return 0;
}
int max_flow(int s, int t){
      int flow = 0;
      for(;;){
            bfs(s);
            if(level[t] < 0) return flow;
            memset(iter, 0, sizeof(iter));
            int f;
            while((f = dfs(s, t, INF)) > 0){
                  flow += f;
            }
      }
}
//------------------上面是最大流模板部分 正确----------------------

int sum;
int mi[maxn];//这个是用来保存每个点的 入度-出度 的值,就是论文里的M(i);

void init(){
      for(int i = 0; i < maxn; i++){//网络流里的清空,不要忘记
            g[i].clear();
      }
      memset(mi, 0, sizeof(mi));
      scanf("%d%d",&n,&m);
      int u, v, d, b;
      for(int i = 1; i <= m; i++){
            scanf("%d%d%d%d",&u, &v, &d, &b);
            mi[u]-=d; mi[v]+=d;
            add_Edge(u, v, b);//加边加上的是每条边的下界值
      }
      sum = 0;//sum保存的是源点的所有流出流量
      for(int i = 1; i <= n; i++){
            if(mi[i] < 0) add_Edge(i, n+1, -mi[i]);
            else if(mi[i] > 0) {
                  add_Edge(0, i, mi[i]);
                  sum += mi[i];
            }
      }
}
void solve(){
      int ans = max_flow(0, n+1);
      if(ans == sum) printf("happy\n");
      else printf("unhappy\n");
}
int main(){
      int t;
      int cas = 0;
      scanf("%d",&t);
      while(t--){
            init();
            printf("Case #%d: ",++cas);
            solve();
      }
      return 0;
}


思路2:

阔以试想~如果对于所有单一的一个点组成的集合S来说,都不能满足 

S到T的路径的费用和 > 毁坏所有T到S的路径的费用和 + 重建这些T到S的双向路径的费用和 的话,那么任意的点的集合构成的S集合也一定并不能满足上述条件~~~反之如果存在集合满足上述条件的话,就一定存在单一的点满足上述条件~~~~

这样我们其实只用枚举点然后判断就好啦。。。。。Orz。。。

code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
const int maxn = 205;

int n, m;

int D[maxn][maxn], B[maxn][maxn];
vector<int> in[maxn], out[maxn];

void init(){
      for(int i = 0; i < maxn; i++){
            in[i].clear();
            out[i].clear();
      }
      memset(D,0,sizeof(D));
      memset(B,0,sizeof(B));
      scanf("%d%d",&n,&m);
      int u, v, dd, bb;
      for(int i = 1; i <= m; i++){
            scanf("%d%d%d%d",&u,&v,&dd,&bb);
            out[u].push_back(v);
            in[v].push_back(u);
            D[u][v] = dd;
            B[u][v] = bb;
      }
}
bool deal(int u){
      int x = 0;
      for(int i = 0; i < in[u].size(); i++){
            int v = in[u][i];
            x += D[v][u];
      }
      int y = 0;
      for(int i = 0; i < out[u].size(); i++){
            int v = out[u][i];
            y = y + D[u][v] + B[u][v];
      }
      if(y < x) return true;
      return false;
}
void solve(){
      for(int i = 1; i <= n; i++){
            if(deal(i)){
                  printf("unhappy\n");
                  return;
            }
      }
      printf("happy\n");
}
int main(){
      int t;
      int cas = 0;
      scanf("%d",&t);
      while(t--){
            init();
            printf("Case #%d: ",++cas);
            solve();
      }
      return 0;
}




0
0
查看评论

无源汇有上下界可行流(网络流进阶)

无源汇有上下界可行流(也就是循环流)模型:一个网络,求出一个流,使得每条边的流量必须>=Li且<=Hi, 每个点必须满足总流入量=总流出量(流量守恒)(这个流的特点是循环往复,无始无终)可行流算法的核心是将一个不满足流量守恒的初始流调整成满足流量守恒的流流量守恒,即每个点的总流入量=总...
  • wu_tongtong
  • wu_tongtong
  • 2017-06-16 07:47
  • 548

无源无汇带上下界的可行流

有上下界网络流问题 1.无源汇最大流 2.有源汇最大流 3.有源汇最小流 1.无源汇最大流问题 sgu194 题意:    给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使...
  • z309241990
  • z309241990
  • 2014-08-13 08:53
  • 3031

无源汇有上下界可行流存在定理

H - Reactor Cooling Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%lld & %...
  • u013067907
  • u013067907
  • 2014-08-10 11:11
  • 1158

POJ 2396 Budget(无源汇网络有上下界的可行流-Dinic)

Description 有一个n*m的方阵,里面的数字未知,但是我们知道如下约束条件: 每一行的数字的和 每一列的数字的和 某些格子有特殊的大小约束,用大于号,小于号和等于号表示 问:是否存在用正数填充这个方阵的方案,满足所有的约束,若有,输出之,否则输出IMPOSSIBLE Input...
  • V5ZSQ
  • V5ZSQ
  • 2015-08-12 11:52
  • 862

LOJ模板题 无源汇有上下界可行流

https://loj.ac/problem/115 没有loj我都不知道有这种操作。 如何求得一个无源汇的图是否可行呢,是一个网络流可以解决的问题。 首先,我们知道每条边的起点u,终点v,下界low,上界up。最初始的图理应是由各条边的下界流量组成的。 然后我们看一看每个点是否能做到流...
  • llzhh
  • llzhh
  • 2017-07-31 12:27
  • 123

bzoj 1927: [Sdoi2010]星际竞速 (无源汇有上下界最小费用可行流) [省选计划系列]

1927: [Sdoi2010]星际竞速 Time Limit: 20 Sec  Memory Limit: 259 MB Submit: 2035  Solved: 1256 [Submit][Status][Disc...
  • qq_34564984
  • qq_34564984
  • 2017-01-02 13:31
  • 383

无源汇有上下界可行流详解(loj115)

例题链接 先解释一下流量平衡。 每条边有出发点和结束点。 出发点就有流出的流量,结束点就有流入的流量。 流量平衡是所有节点流入流量等于流出流量。这种问题的思想就是: 在一个初始流的基础上加上一个附加流。 每条边的流量有上下界。那么初始每条边的流量就为每条边的下界。 用d数组表示每个点的...
  • Hanks_o
  • Hanks_o
  • 2017-09-13 21:02
  • 190

HDU 4940 无源无汇上下界最大流

对于每条有向边lai's
  • ipqhjjybj
  • ipqhjjybj
  • 2014-08-13 12:21
  • 1327

loj #115. 无源汇有上下界可行流

题目链接:https://loj.ac/problem/115 参考博客:http://www.cnblogs.com/liu-runda/p/6262832.html 模型:一个网络,求出一个流,使得每条边的流量必须>=Li且 这个算法是有上下界网络流算法的基础,只要深刻理解这...
  • sinat_32872703
  • sinat_32872703
  • 2017-10-17 22:00
  • 96

HDU 4940 Destroy Transportation system(上下界网络流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4940 题意:给出一张有向强连通图,每条边有两个权值分别是破坏该边的权值和修建双向边的权值(修建前要先破坏),对于一个集合S和S的补集T,破坏所有从S到T的边的权值和为X,修建T到S的双向边的权值和...
  • u013742332
  • u013742332
  • 2015-08-08 21:43
  • 304
    个人资料
    • 访问:142350次
    • 积分:3191
    • 等级:
    • 排名:第12781名
    • 原创:175篇
    • 转载:6篇
    • 译文:9篇
    • 评论:13条
    博客专栏