Description

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

Let’s represent his enemy’s transportation system as a simple directed graph G with n nodes and m edges. Each node is a city and each directed edge is a directed road. Each edge from node u to node v is associated with two values D and B, D is the cost to destroy/remove such edge, B is the cost to build an undirected edge between u and v.

His enemy can deliver supplies from city u to city v if and only if there is a directed path from u to v. At first they can deliver supplies from any city to any other cities. So the graph is a strongly-connected graph.

He will choose a non-empty proper subset of cities, let’s denote this set as S. Let’s denote the complement set of S as T. He will command his soldiers to destroy all the edges (u, v) that u belongs to set S and v belongs to set T.

To destroy an edge, he must pay the related cost D. The total cost he will pay is X. You can use this formula to calculate X:

After that, all the edges from S to T are destroyed. In order to deliver huge number of supplies from S to T, his enemy will change all the remained directed edges (u, v) that u belongs to set T and v belongs to set S into undirected edges. (Surely, those edges exist because the original graph is strongly-connected)

To change an edge, they must remove the original directed edge at first, whose cost is D, then they have to build a new undirected edge, whose cost is B. The total cost they will pay is Y. You can use this formula to calculate Y:

At last, if Y>=X, Tom will achieve his goal. But Tom is so lazy that he is unwilling to take a cup of time to choose a set S to make Y>=X, he hope to choose set S randomly! So he asks you if there is a set S, such that Y<X. If such set exists, he will feel unhappy, because he must choose set S carefully, otherwise he will become very happy.

Input

There are multiply test cases.

The first line contains an integer T(T<=200), indicates the number of cases.

For each test case, the first line has two numbers n and m.

Next m lines describe each edge. Each line has four numbers u, v, D, B. 
(2=<n<=200, 2=<m<=5000, 1=<u, v<=n, 0=<D, B<=100000)

The meaning of all characters are described above. It is guaranteed that the input graph is strongly-connected.

Output

For each case, output "Case #X: " first, X is the case number starting from 1.If such set doesn’t exist, print “happy”, else print “unhappy”.

Sample Input

2
3 3
1 2 2 2
2 3 2 2
3 1 2 2
3 3
1 2 10 2
2 3 2 2
3 1 2 2

Sample Output

Case #1: happy
Case #2: unhappy
Hint

In first sample, for any set S, X=2, Y=4. In second sample. S= {1}, T= {2, 3}, X=10, Y=4.

Source

2014 Multi-University Training Contest 7
 
先来一个错误但是AC了(数据水)的算法:

每个点单独作为S集合时,如果存在满足Y<X,就输出unhappy。否则输出happy。

 

为什么错呢?输出happy时,即两个点单独作为S时,都有Y1>=X1,Y2>=X2,如果两个点之间没有边,它们一起作为S时,X=X1+X2,Y=Y1+Y2,则Y>=X;但是如果两个点有边相连,X=X1+X2-(S1到S2的D)-(S2到S1的D),Y=Y1+Y2-(S1到S2的D+B)-(S2到S1的D+B),那么Y+B12+B21>=X,就有可能是Y<X了。当输入

1
4 5
1 4 10 2
4 1 6 2
2 1 1 1
4 3 6 2
3 2 4 2

时,输出的是happy。可是实际上,选择1、4节点,Y=2,X=8,显然是unhappy。

附上非正解代码:(AC了只能说明题目数据太水了)

#include <cstdio>
#include <cstring>
#define N 205
#define sf(x) scanf("%d",&x)
int x[N],y[N];
int main(){
int t;
sf(t);
for(int cas=;cas<=t;cas++){
memset(x,,sizeof x);
memset(y,,sizeof y);
printf("Case #%d: ",cas);
int n,m;
sf(n);
sf(m);
for(int i=;i<=m;i++){
int u,v,d,b;
sf(u);sf(v);sf(d);sf(b);
x[u]+=d;
y[v]+=d+b;
}
int ok=;
for(int i=;i<=n;i++)
if(x[i]>y[i])ok=;
if(ok)puts("happy");
else puts("unhappy");
}
}

正解是无源无汇带上下界判断是否有可行流。

将问题转化为网络流问题:
每条边下界为D,上界为D+B,如果存在可行流,那么
$$\sum_{\substack{u\in S \\ v\in \overline {S}}} f_{uv} = \sum_{\substack{u\in S \\ v\in \overline {S}}}f_{uv}\\D_{uv} \leq f_{uv} \leq D_{uv}+B_{uv}$$
所以有
$$\sum_{\substack{u\in S \\ v\in \overline {S}}} D_{uv} \leq \sum_{\substack{u\in S \\ v\in \overline {S}}}D_{uv}+ B_{uv}$$
因此只要求无源无汇上下界网络流是否存在可行流,如果不存在就是unhappy。
而无源汇有上下界的网络流,是否有可行流可以这样求:
人为加上源点s,汇点t,
边权改为上界-下界(这样转化为下界为0),
流入i点的下界和为in,流出的下界和为out,
in>out则s 到 i 连边,流量为in-out;
in<out则 i 到 t 连边,流量为out-in。

求s到t的最大流,如果源点汇点连接的边全部满流则有可行解。

参考国家集训队论文《一种简易的方法求解流量有上下界的网络中网络流问题》

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define N 500
#define M 200001
#define inf 0x3f3f3f3f
struct edge{
int to,next,cap,flow;
}e[M];
int head[N],cnt;
int gap[N],dep[N],cur[N];
void init(){
cnt=;
memset(head, -, sizeof head);
}
void add(int u,int v,int w,int rw=){
e[cnt]=(edge){v,head[u],w,};
head[u]=cnt++;
e[cnt]=(edge){u,head[v],rw,};
head[v]=cnt++;
}
int q[N];
void bfs(int st,int ed){
memset(dep,-,sizeof dep);
memset(gap,,sizeof gap);
gap[]=;
int front=,rear=;
dep[ed]=;
q[rear++]=ed;
while(front!=rear){
int u=q[front++];
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(dep[v]!=-)continue;
q[rear++]=v;
dep[v]=dep[u]+;
gap[dep[v]]++;
}
}
}
int s[N];
int sap(int st,int ed,int n){
bfs(st,ed);
memcpy(cur,head,sizeof head);
int top=;
int u=st;
int ans=;
while(dep[st]<n){
if(u==ed){
int Min=inf;
int inser;
for(int i=;i<top;i++)
if(Min>e[s[i]].cap-e[s[i]].flow){
Min=e[s[i]].cap-e[s[i]].flow;
inser=i;
}
for(int i=;i<top;i++){
e[s[i]].flow+=Min;
e[s[i]^].flow-=Min;
}
ans+=Min;
top=inser;
u=e[s[top]^].to;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];~i;i=e[i].next){
v=e[i].to;
if(e[i].cap-e[i].flow&&dep[v]+==dep[u]){
flag=true;
cur[u]=i;
break;
}
}
if(flag){
s[top++]=cur[u];
u=v;
continue;
}
int Min=n;
for(int i=head[u];~i;i=e[i].next)
if(e[i].cap-e[i].flow &&dep[e[i].to]<Min){
Min=dep[e[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if(!gap[dep[u]])return ans;
gap[dep[u]=Min+]++;
if(u!=st)u=e[s[--top]^].to;
}
return ans;
}
int main(){
int t;
scanf("%d",&t);
for(int cas=;cas<=t;cas++){
printf("Case #%d: ",cas);
int n,m;
scanf("%d%d",&n,&m);
int in[N];
int st=,ed=n+;
memset(in,,sizeof in);
init();
for(int i=;i<=m;i++){
int u,v,d,b;
scanf("%d%d%d%d",&u,&v,&d,&b);
add(u,v,b);
in[v]+=d;
in[u]-=d;
}
int need=;
for(int i=;i<=n;i++){
if(in[i]>){
add(st,i,in[i]);
need+=in[i];
}
else add(i,ed,-in[i]);
}
int ans=sap(st, ed, ed+);
if(need==ans)puts("happy");
else puts("unhappy");
}
}

【HDU 4940】Destroy Transportation system(无源无汇带上下界可行流)的更多相关文章

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

    题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到 ...

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

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

  3. SGU 194 Reactor Cooling 无源汇带上下界可行流

    Reactor Cooling time limit per test: 0.5 sec. memory limit per test: 65536 KB input: standard output ...

  4. POJ 2396 有源有汇有上下界可行流问题

    题意:给一个矩阵,给出每行每列之和,附加一些条件,如第i行第j列数必需大于(小于)多少. 思路题解:矩阵模型,模拟网络流,行.列标号为结点,构图,附加s,t,s连行标(容量上下限每行之和(必需以这个 ...

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

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

  6. [ACdream 1211 Reactor Cooling]无源无汇有上下界的可行流

    题意:无源无汇有上下界的可行流 模型 思路:首先将所有边的容量设为上界减去下界,然后对一个点i,设i的所有入边的下界和为to[i],所有出边的下界和为from[i],令它们的差为dif[i]=to[i ...

  7. LOJ [#115. 无源汇有上下界可行流](https://loj.ac/problem/115)

    #115. 无源汇有上下界可行流 先扔个板子,上下界的东西一点点搞,写在奇怪的合集里面 Code: #include <cstdio> #include <cstring> # ...

  8. 2018.08.20 loj#115. 无源汇有上下界可行流(模板)

    传送门 又get到一个新技能,好兴奋的说啊. 一道无源汇有上下界可行流的模板题. 其实这东西也不难,就是将下界变形而已. 准确来说,就是对于每个点,我们算出会从它那里强制流入与流出的流量,然后与超级源 ...

  9. [loj#115] 无源汇有上下界可行流 网络流

    #115. 无源汇有上下界可行流 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据   题 ...

随机推荐

  1. combobox 属性、事件、方法

    一 .combobox 属性.事件.方法公共属性 名称 说明 AccessibilityObject 获取分配给该控件的 AccessibleObject. AccessibleDefaultActi ...

  2. [转] 如何设置Eclipse的上网代理

    from: http://blog.csdn.net/qq635785620/article/details/8191799 不同版本的eclipse有不同的设置方法 方式一:   默认的Eclips ...

  3. android之android.intent.category.DEFAULT的用途和使用

    1.要弄清楚这个问题,首先需要弄明白什么是implicit(隐藏) intent什么是explicit(明确) intent. Explicit Intent明确的指定了要启动的Acitivity , ...

  4. AngularJs 时间格式化处理

    1.AngularJs的controller中格式: var dateAsString = $filter('date')(item_date, "yyyy-MM-dd hh:mm:ss&q ...

  5. 关于高负载服务器Kernel的TCP参数优化

    net.ipv4.tcp_mem 内核分配给TCP连接的内存,单位是Page,1 Page = 4096 Bytes,可用命令查看: #getconf PAGESIZE 4096 net.ipv4.t ...

  6. 线程 VS 进程

    线程是指进程内的一个执行单元,也是进程内的可调度实体. 与进程的区别: (1)地址空间:进程内的一个执行单元;进程至少有一个线程;它们共享进程的地址空间;而进程有自己独立的地址空间; (2)资源拥有: ...

  7. C# 断点续传原理与实现

    在了解HTTP断点续传的原理之前,让我们先来了解一下HTTP协议,HTTP协议是一种基于tcp的简单协议,分为请求和回复两种.请求协议是由 客户机(浏览器)向服务器(WEB SERVER)提交请求时发 ...

  8. Delphi项目的构成

    Hello.cfg 項目配置文件 Hello.dof 項目選項文件 Hello.dpr 項目文件 Hello.exe 應用程序 Hello.res 資源文件 HelloWorld.dcu 窗口編譯文件 ...

  9. Android手机浏览器访问本地网络相关问题

    为了测试开发的手机网站,常常需要使手机直接访问本地网络. 在这个过程中碰到几个问题,记下来供以后参考 1. 在本地主机运行apache后,使用localhost和127.0.0.1可以访问页面,但使用 ...

  10. Html5 Egret游戏开发 成语大挑战(三)开始界面

    本篇需要在前面的素材准备完毕,才可以开始,使用egret的eui结合代码编辑,快速完成基本的界面搭建,这里写的可能比较细,目的是减少大家对于其中一些操作疑问,我去掉了很多无用的步骤,以最精简的流程来完 ...