您的位置:首页 > 其它

hdu4940 Destroy Transportation system

2014-08-13 10:19 204 查看
给你一个强连通的有向简单图,每条边有D, B两个权值,设S为点集的一个非空真子集

问:是否对于任意的集合S,都有sum (D(i, j))<= sum(D(j, i) + B(j, i)),(i, j)是点集S和S'的割边

比赛的时候完全没有思路啊。。。最大流果然还是白板

思路:将D值作为边的下界,D + B作为边的上界,如果存在可行流,那么对于任意集合S

都有流量小于等于边的容量上界,大于等于边的容量下界,即D(i, j) <= f(i, j) <= D(j, i)+B(j, i)

这就将问题转化为了裸的有下界的最大流,解决方法见这里

#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <bitset>
#include <fstream>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//OTHER
#define PB push_back
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)

#define sqr(x) (x) * (x)
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const double eps = 1e-9;
const int MOD = 1000000007;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int maxn = 250;

/////Dinic算法//////
struct Edge{
int from, to, cap, flow;
};

struct Dinic{
int n, m ,s, t;
vector<Edge> edges;
VI G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn]   ;

void init(int nn)
{
this->n = nn;
REP(i, n + 2) G[i].clear();
edges.clear();
}

void addEdge(int from, int to, int cap)
{
edges.PB((Edge){from, to, cap, 0});
edges.PB((Edge){to, from, 0, 0});
m = edges.size();
G[from].PB(m - 2);
G[to].PB(m - 1);
}

bool bfs()
{
CLR(vis, 0);
queue<int> Q;
Q.push(s);
d[s] = 0;
vis[s] = 1;
while (!Q.empty())
{
int x = Q.front();
Q.pop();
REP(i, G[x].size())
{
Edge& e = edges[G[x][i]];
if (!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}

int dfs(int x, int a)
{
if (x == t || a == 0)   return a;
int flow = 0, f;
for (int& i = cur[x]; i < G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
{
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
//当所求流量大于need时就退出,降低时间
int maxflow(int s,int t,int need){
this->s = s; this->t = t;
int flow = 0;
while(bfs())
{
CLR(cur ,0);
flow += dfs(s,INF);
if (flow > need)
return flow;
}
return flow;
}
//最小割割边
vector<int> Mincut(){
BFS();
vector<int> ans;
for (int i = 0; i < edges.size(); i++){
Edge& e = edges[i];
if (vis[e.from] && !vis[e.to] && e.cap > 0)
ans.push_back(i);
}
return ans;
}
void Reduce(){
for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
}
void ClearFlow(){
for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
}
}sol;

int sum[maxn];

int main()
{
//freopen("0.txt", "r", stdin);
int T, x, y, b, d, tot;
int n, m;
RI(T);
FE(kase, 1, T)
{
CLR(sum, 0), tot = 0;
RII(n, m);
sol.init(n + 2);
REP(i, m)
{
RIV(x, y, d, b);
sum[x] -= d;
sum[y] += d;
sol.addEdge(x, y, b);
}
FE(i, 1, n)
if (sum[i] > 0)
sol.addEdge(0, i, sum[i]), tot += sum[i];
else if (sum[i] < 0)
sol.addEdge(i, n + 1, -sum[i]);
int ans = sol.maxflow(0, n + 1, INF);
printf("Case #%d: ", kase);
if (ans == tot)
puts("happy");
else
puts("unhappy");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: