给你一个强连通的有向简单图,每条边有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; }
hdu4940 Destroy Transportation system,布布扣,bubuko.com
hdu4940 Destroy Transportation system
原文地址:http://blog.csdn.net/colin_27/article/details/38532709