题意:
有n个士兵,你可以选择让它成为战士还是法师。
有m对关系,u和v 如果同时为战士那么你可以获得a的权值
如果同时为法师,你可以获得c的权值,
如果一个为战士一个是法师,你可以获得b的权值
问你可以获得的最大权值是多少?
题解:
对每个士兵建立一个点x ,点x 向源点s 连一条边,向汇点t 连一条边,
分别表示选择两种职业,然后就可以先加上所有的贡献,通过两点关系用 最小割建模,如下图所示
设一条边的三种贡献为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即可
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