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

675人阅读 评论(0)

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

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


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

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

个人资料
• 访问：142350次
• 积分：3191
• 等级：
• 排名：第12781名
• 原创：175篇
• 转载：6篇
• 译文：9篇
• 评论：13条
博客专栏
 acm-icpc竞赛时光记 文章：113篇 阅读：83520
阅读排行