标签:and min efi cas flow make contains input 定向
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1669 Accepted Submission(s): 682
解析:
每条边由两种选择,删除还是不删除,这两者所用的权值都是正数,如果一正一负是不是就是最大权闭合子图
其实这题就和欧拉路的混合图建边一样 先定向建边 然后反悔
但这个不是 ,所以我们可以对一条边进行假设,如果边 u - > v 的 a < b 那么我们在原图中就保留这条边 sum += a,网络图中 建一条v - > u的反向边 权值为b - a in[v]++, out[u]++ (这里统计的是原图中的度数) 如果求费用流时走了这条边就意味着 原图中不走这条边 也就是删除这条边,同理 b < a 但这一步不统计度数 因为这一步的边在原图中已经删除了
然后in[s_]++, out[t_]++ 使得每个节点入度 = 出度
但实际却不是这样,通过这样构建图之后,原图中并不是所有的点的入度等于出度, 所以要通过网络图进行调整,
遍历每个点如果in[i] < out[i] 则从i 到 t 添加一条权值为out[i] - in[i]的边,注意这里in[i] out[i]是统计的原图中的度数,|out[i] - in[i]| 表示原图中出度和入度的差额 这里的权值为|out[i] - in[i]|, 而混合欧拉图中的权值为|out[i] - in[i]| / 2,知道为什么嘛。。。因为这里是删除边 而 混合欧拉图里是把边反向 嗯 是的 我和个傻子一样
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <cctype> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #include <bitset> #define rap(i, a, n) for(int i=a; i<=n; i++) #define rep(i, a, n) for(int i=a; i<n; i++) #define lap(i, a, n) for(int i=n; i>=a; i--) #define lep(i, a, n) for(int i=n; i>a; i--) #define rd(a) scanf("%d", &a) #define rlld(a) scanf("%lld", &a) #define rc(a) scanf("%c", &a) #define rs(a) scanf("%s", a) #define rb(a) scanf("%lf", &a) #define rf(a) scanf("%f", &a) #define pd(a) printf("%d\n", a) #define plld(a) printf("%lld\n", a) #define pc(a) printf("%c\n", a) #define ps(a) printf("%s\n", a) #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 2222222, INF = 0x3f3f3f3f, LL_INF = 0x7fffffffffffffff; int n, m, k, q, s, t; int head[222], d[222], vis[222], p[222], f[222], nex[maxn]; int in[222], out[222]; int flow, value, cnt; struct node { int u, v, w, c; }Node[maxn]; void add_(int u, int v, int w, int c) { Node[cnt].u = u; Node[cnt].v = v; Node[cnt].w = w; Node[cnt].c = c; nex[cnt] = head[u]; head[u] = cnt++; } void add(int u, int v, int w, int c) { add_(u, v, w, c); add_(v, u, -w, 0); } int spfa() { deque<int> Q; mem(vis, 0); mem(p, -1); mem(d, INF); d[s] = 0; Q.push_front(s); vis[s] = 1; p[s] = 0, f[s] = INF; while(!Q.empty()) { int u = Q.front(); Q.pop_front(); vis[u] = 0; for(int i = head[u]; i != -1; i = nex[i]) { node e = Node[i]; if(d[e.v] > d[u] + Node[i].w && Node[i].c > 0) { d[e.v] = d[u] + Node[i].w; p[e.v] = i; f[e.v] = min(f[u], Node[i].c); if(!vis[e.v]) { if(Q.empty()) Q.push_front(e.v); else { if(d[e.v] < d[Q.front()]) Q.push_front(e.v); else Q.push_back(e.v); } vis[e.v] = 1; } } } } if(p[t] == -1) return 0; flow += f[t]; value += f[t] * d[t]; for(int i = t; i != s; i = Node[p[i]].u) { Node[p[i]].c -= f[t]; Node[p[i] ^ 1].c += f[t]; } return 1; } void max_flow() { value = flow = 0; while(spfa()); } void init() { mem(head, -1); mem(in, 0); mem(out, 0); cnt = 0; } int main() { int T, kase = 0; rd(T); while(T--) { init(); int u, v, a, b, s_, t_; int sum = 0, sum_flow = 0; rd(n), rd(m), rd(s_), rd(t_); s = 0, t = n + 1; rap(i, 1, m) { rd(u), rd(v), rd(a), rd(b); if(a < b) { sum += a; add(v, u, b - a, 1); in[v]++, out[u]++; } else { sum += b; add(u, v, a - b, 1); // in[v]++, out[u]++; } } // add(t_, s_, 0, 1); in[s_]++, out[t_]++; rap(i, 1, n) { cout << in[i] - out[i] << endl; if(in[i] < out[i]) add(i, t, 0, (out[i] - in[i])); else if (in[i] > out[i]) add(s, i, 0, (in[i] - out[i])), sum_flow += (in[i] - out[i]); } max_flow(); // cout << sum_flow << " " << flow << endl; printf("Case %d: ", ++kase); if(sum_flow != flow) { ps("impossible"); } else pd(sum + value); } return 0; }
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1669 Accepted Submission(s): 682
Random Maze HDU - 4067(预定义状态建边(贪心建边))
标签:and min efi cas flow make contains input 定向
原文地址:https://www.cnblogs.com/WTSRUVF/p/9947023.html