2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型

题意:

有n个士兵,你可以选择让它成为战士还是法师。

有m对关系,u和v 如果同时为战士那么你可以获得a的权值

如果同时为法师,你可以获得c的权值,

如果一个为战士一个是法师,你可以获得b的权值

问你可以获得的最大权值是多少?

 

题解:

对每个士兵建立一个点x ,点x 向源点s 连一条边,向汇点t 连一条边,

分别表示选择两种职业,然后就可以先加上所有的贡献,通过两点关系用 最小割建模,如下图所示

2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型

 

设一条边的三种贡献为A, B, C,可以得到以下方程:

如果x,y都是法师,你可以获得C的权值,但是我们构建的是最小割模型(这个权值C应该是A+B+C-该图的最小割),

我们选择x,y都是法师的最小割对应的权值应该是A+B,对应的边根据上述是a,b

所以有a+b=A+B

同理对于都是战士有公式c+d=B+C

对于一战士一法师有公式a+e+d=A+C   b+e+c=A+C

存在一组解

a=b=(A+B)/2,c=d=(C+B)/2,e=-B+(A+C)/2;

为了消除浮点数的问题,我们建边的时候将边权*2,取答案的时候/2即可

 

2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型
  1 #include <set>
  2 #include <map>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 #include <unordered_map>
 14 
 15 #define  pi    acos(-1.0)
 16 #define  eps   1e-9
 17 #define  fi    first
 18 #define  se    second
 19 #define  rtl   rt<<1
 20 #define  rtr   rt<<1|1
 21 #define  bug                printf("******\n")
 22 #define  mem(a, b)          memset(a,b,sizeof(a))
 23 #define  name2str(x)        #x
 24 #define  fuck(x)            cout<<#x" = "<<x<<endl
 25 #define  sfi(a)             scanf("%d", &a)
 26 #define  sffi(a, b)         scanf("%d %d", &a, &b)
 27 #define  sfffi(a, b, c)     scanf("%d %d %d", &a, &b, &c)
 28 #define  sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
 29 #define  sfL(a)             scanf("%lld", &a)
 30 #define  sffL(a, b)         scanf("%lld %lld", &a, &b)
 31 #define  sfffL(a, b, c)     scanf("%lld %lld %lld", &a, &b, &c)
 32 #define  sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d)
 33 #define  sfs(a)             scanf("%s", a)
 34 #define  sffs(a, b)         scanf("%s %s", a, b)
 35 #define  sfffs(a, b, c)     scanf("%s %s %s", a, b, c)
 36 #define  sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d)
 37 #define  FIN                freopen("../in.txt","r",stdin)
 38 #define  gcd(a, b)          __gcd(a,b)
 39 #define  lowbit(x)          x&-x
 40 #define  IO                 iOS::sync_with_stdio(false)
 41 
 42 
 43 using namespace std;
 44 typedef long long LL;
 45 typedef unsigned long long ULL;
 46 const ULL seed = 13331;
 47 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
 48 const int maxn = 500 + 7;
 49 const int maxm = 2e5 + 10;
 50 const int INF = 0x3f3f3f3f;
 51 const int mod = 1e9 + 7;
 52 int n, m;
 53 
 54 struct MaxFlow {
 55     struct Edge {
 56         int v, nxt;
 57         LL w;
 58     } edge[maxm];
 59     int tot, num, s, t;
 60     int head[maxn];
 61 
 62     void init() {
 63         memset(head, -1, sizeof(head));
 64         tot = 0;
 65     }
 66 
 67     void add(int u, int v, LL w) {
 68         edge[tot] = (Edge) {
 69                 v, head[u], w
 70         };
 71         head[u] = tot++;
 72         edge[tot] = (Edge) {
 73                 u, head[v], 0
 74         };
 75         head[v] = tot++;
 76     }
 77 
 78     int d[maxn], vis[maxn], gap[maxn];
 79 
 80     void bfs() {
 81         memset(d, 0, sizeof(d));
 82         memset(gap, 0, sizeof(gap));
 83         memset(vis, 0, sizeof(vis));
 84         queue<int> q;
 85         q.push(t);
 86         vis[t] = 1;
 87         while (!q.empty()) {
 88             int u = q.front();
 89             q.pop();
 90             for (int i = head[u]; ~i; i = edge[i].nxt) {
 91                 int v = edge[i].v;
 92                 if (!vis[v]) {
 93                     d[v] = d[u] + 1;
 94                     gap[d[v]]++;
 95                     q.push(v);
 96                     vis[v] = 1;
 97                 }
 98             }
 99         }
100     }
101 
102     int last[maxn];
103 
104     LL dfs(int u, LL f) {
105         if (u == t) return f;
106         LL sap = 0;
107         for (int i = last[u]; ~i; i = edge[i].nxt) {
108             int v = edge[i].v;
109             if (edge[i].w > 0 && d[u] == d[v] + 1) {
110                 last[u] = i;
111                 LL tmp = dfs(v, min(f - sap, edge[i].w));
112                 edge[i].w -= tmp;
113                 edge[i ^ 1].w += tmp;
114                 sap += tmp;
115                 if (sap == f) return sap;
116             }
117         }
118         if (d[s] >= num) return sap;
119         if (!(--gap[d[u]])) d[s] = num;
120         ++gap[++d[u]];
121         last[u] = head[u];
122         return sap;
123     }
124 
125     LL solve(int st, int ed, int n) {
126         LL flow = 0;
127         num = n;
128         s = st;
129         t = ed;
130         bfs();
131         memcpy(last, head, sizeof(head));
132         while (d[s] < num) flow += dfs(s, INFLL);
133         return flow;
134     }
135 } F;
136 
137 int main() {
138     //FIN;
139     while (~sffi(n, m)) {
140         F.init();
141         LL sum = 0;
142         for (int i = 0, u, v, a, b, c; i < m; ++i) {
143             sffi(u, v);
144             sfffi(a, b, c);
145             F.add(0, u, a + b);
146             F.add(0, v, a + b);
147             F.add(u, n + 1, b + c);
148             F.add(v, n + 1, b + c);
149             F.add(u, v, -2 * b + a + c);
150             F.add(v, u, -2 * b + a + c);
151             sum += a + b + c;
152         }
153         printf("%lld\n", (2 * sum - F.solve(0, n + 1, n + 2)) / 2);
154     }
155     return 0;
156 }
View Code

 

上一篇:POJ 3069 Saruman's Army


下一篇:poj 3069 Saruman's Army 贪心模拟