Random Maze HDU - 4067(预定义状态建边(贪心建边))
Posted wtsruvf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Random Maze HDU - 4067(预定义状态建边(贪心建边))相关的知识,希望对你有一定的参考价值。
Random Maze
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1669 Accepted Submission(s): 682
1.There is only one entrance and one exit.
2.All the road in the maze are unidirectional.
3.For the entrance, its out-degree = its in-degree + 1.
4.For the exit, its in-degree = its out-degree + 1.
5.For other node except entrance and exit, its out-degree = its in-degree.
There is an directed graph, your task is removing some edge so that it becomes a random maze. For every edge in the graph, there are two values a and b, if you remove the edge, you should cost b, otherwise cost a.
Now, give you the information of the graph, your task if tell me the minimum cost should pay to make it becomes a random maze.
The rest of the test file contains T blocks.
For each test case, there is a line with four integers, n, m, s and t, means that there are n nodes and m edges, s is the entrance‘s index, and t is the exit‘s index. Then m lines follow, each line consists of four integers, u, v, a and b, means that there is an edge from u to v.
2<=n<=100, 1<=m<=2000, 1<=s, t<=n, s != t. 1<=u, v<=n. 1<=a, b<=100000
解析:
每条边由两种选择,删除还是不删除,这两者所用的权值都是正数,如果一正一负是不是就是最大权闭合子图
其实这题就和欧拉路的混合图建边一样 先定向建边 然后反悔
但这个不是 ,所以我们可以对一条边进行假设,如果边 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 ", a) #define plld(a) printf("%lld ", a) #define pc(a) printf("%c ", a) #define ps(a) printf("%s ", 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; }
Random Maze
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1669 Accepted Submission(s): 682
1.There is only one entrance and one exit.
2.All the road in the maze are unidirectional.
3.For the entrance, its out-degree = its in-degree + 1.
4.For the exit, its in-degree = its out-degree + 1.
5.For other node except entrance and exit, its out-degree = its in-degree.
There is an directed graph, your task is removing some edge so that it becomes a random maze. For every edge in the graph, there are two values a and b, if you remove the edge, you should cost b, otherwise cost a.
Now, give you the information of the graph, your task if tell me the minimum cost should pay to make it becomes a random maze.
The rest of the test file contains T blocks.
For each test case, there is a line with four integers, n, m, s and t, means that there are n nodes and m edges, s is the entrance‘s index, and t is the exit‘s index. Then m lines follow, each line consists of four integers, u, v, a and b, means that there is an edge from u to v.
2<=n<=100, 1<=m<=2000, 1<=s, t<=n, s != t. 1<=u, v<=n. 1<=a, b<=100000
以上是关于Random Maze HDU - 4067(预定义状态建边(贪心建边))的主要内容,如果未能解决你的问题,请参考以下文章