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

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

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

思路1:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" align="middle" alt="">

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

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

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;
}

hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )的更多相关文章

  1. HDU 4940 Destroy Transportation system(无源汇上下界网络流)

    Problem Description Tom is a commander, his task is destroying his enemy’s transportation system. Le ...

  2. [Ahoi2014]支线剧情[无源汇有下界最小费用可行流]

    3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1538  Solved: 940[Submit][Statu ...

  3. hdu 4940 Destroy Transportation system (无源汇上下界可行流)

    Destroy Transportation system Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 ...

  4. hdu 4940 Destroy Transportation system(水过)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4940 Destroy Transportation system Time Limit: 2000/1 ...

  5. HDU 4940 Destroy Transportation system(无源汇有上下界最大流)

    看不懂题解以及别人说的集合最多只有一个点..... 然后试了下题解的方法http://blog.sina.com.cn/s/blog_6bddecdc0102uzka.html 首先是无源汇有上下界最 ...

  6. HDU 4940 Destroy Transportation system(2014 Multi-University Training Contest 7)

    思路:无源汇有上下界可行流判定, 原来每条边转化成  下界为D  上界为 D+B   ,判断是否存在可行流即可. 为什么呢?  如果存在可行流  那么说明对于任意的 S 集合流出的肯定等于 流入的, ...

  7. ZOJ 2314 Reactor Cooling(无源汇上下界网络流)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2314 题意: 给出每条边流量的上下界,问是否存在可行流,如果存在则输出. ...

  8. sgu 176 上下界网络流最小可行流带输出方案

    算法步骤: 1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流. 2. 加上刚才没有加上的那条边p 3. 再 ...

  9. POJ 2396 Budget (上下界网络流有源可行流)

    转载: http://blog.csdn.net/axuan_k/article/details/47297395 题目描述: 现在要针对多赛区竞赛制定一个预算,该预算是一个行代表不同种类支出.列代表 ...

随机推荐

  1. _int64、long long 的区别

    C++的64位整数[原]by 赤兔 http://baike.baidu.com/view/1235293.htm 在做ACM题时,经常都会遇到一些比较大的整数.而常用的内置整数类型常常显得太小了:其 ...

  2. 使用python操作RabbitMQ,Redis,Memcache,SQLAlchemy 其二

    一.概念 1.Memcached     Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态 ...

  3. poj 1080

    http://poj.org/problem?id=1080 知识点 :最长公共子序列 要点: 转移方程  f[i][j]  = max{ f[i-i][j]+score[s1[i-1]]['-'], ...

  4. C语言之猜数字游戏

    猜数字游戏 猜数字游戏是以前功能机上的一款益智游戏,计算机会根据输入的位数随机分配一个符合要求的数据,计算机输出guess后便可以输入数字,注意数字间需要用空格或回车符加以区分,计算机会根据输入信息给 ...

  5. C++堆和栈的比较(7个区别)

    基础知识: 堆 栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表.允许插入或删除操作的一端称为栈顶,另一端称为栈底,对堆栈的插入和删除操作被称 为入栈和出栈.有一组CPU指令可以实现 ...

  6. libpng causes error concerning pngconf.h

    Bug Description Ubuntu Gutsy Gibbon 7.10 - libpng 1.2.15~beta5-2ubuntu0.1 (bug probably concerned wi ...

  7. easui tree载入时自动展开无子节点的节点

    利用loadFilter对后台返回的原始数据进行过滤处理,将数据中的state字段修改相应的值,若无子节点,则改成open,若有子节点,则改成closed. 由于一个node属性只有下面几项内容,因此 ...

  8. python手记(41)

    python opencv图片融合 #!/usr/bin/env python #-*- coding: utf-8 -*- #code:myhaspl@qq.com import cv2 impor ...

  9. 【MongoDB】windows平台搭建Mongo数据库复制集(相似集群)(一)

    Replica  Sets(复制集)是在mongodDB1.6版本号開始新增的功能.它能够实现故障自己主动切换和自己主动修复功能成员节点的功能,各个DB之间的数据全然一致,大大减少了单点故障的风险. ...

  10. ceph存储之查找对象

    对象存储(而非块存储): 要把对象存入ceph集群,客户端必须做到: 1.指定对象名 2.指定存储池 Ceph客户端检出最新集群运行图,客户端用CRUSH算法动态地计算出如何把对象映射到归置组.然后计 ...