2019DX#2

2019-07-25

2019DX#2

 

1008 Harmonious Army

题意

有n个士兵,要求分成两组,然后就是某些对士兵间有关系,对于一对关系(u,v,a,b,c),如果u,v在同在Warrior,能得到a,如果同在Mage,则得到c,如果在不同组,则得到b,

问得到最大值是多少。

思路

网络流,自己还是要多练练网络流的题目。

最小割的模型,因为一个士兵要么在Mage,要么在Warrior。

所以我们把Mage当作源点,把Warrior当作汇点。

有关系的两点,有三种关系A,B,C,我们考虑割掉边的不同组合,重新计算出每条边的流量。

最后拿总流量减去最小割即可。

技术图片
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<0||ch>9) f|=(ch==-),ch=getchar();
    while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;

/**********showtime************/
    
            const int maxm = 5e5+9;
            const int maxn = 509;
            struct Edge{
                int v,w;
                int nxt;
            }edge[maxm];
            int gtot = 0, head[maxn];
            void addedge(int u,int v, int w){
                edge[gtot].v = v;
                edge[gtot].w = w;
                edge[gtot].nxt = head[u];
                head[u] = gtot++;

                edge[gtot].v = u;
                edge[gtot].w = 0;
                edge[gtot].nxt = head[v];
                head[v] = gtot++;
            }

            int dis[maxn],cur[maxn];
            bool bfs(int s,int t) {
                for(int i=s; i<=t; i++) {
                    dis[i] = inf;
                    cur[i] = head[i];
                }
                queue<int>que;
                dis[s] = 0;
                que.push(s);
                while(!que.empty()){

                    int u = que.front(); que.pop();
                    for(int i=head[u]; ~i; i = edge[i].nxt){
                        int v = edge[i].v;
                        int w = edge[i].w;
                        if(w > 0 && dis[v] > dis[u] + 1 ) {
                            dis[v] = dis[u] + 1;
                            que.push(v);
                        }
                    }
                }
                return dis[t] < inf;
            }
            ll dfs(int u, int t, ll maxflow) {
                if(u == t || maxflow == 0) return maxflow;
                for(int i=cur[u]; ~i; i=edge[i].nxt){
                    cur[u] = i;
                    int v = edge[i].v;
                    int w = edge[i].w;
                    if(w > 0 && dis[v] == dis[u] + 1){
                        int f = dfs(v, t, min(maxflow, 1ll*w));
                        if(f> 0) {
                            edge[i].w -= f;
                            edge[i ^ 1].w += f;
                            return f;
                        }
                    }
                }
                return 0;
            }
            ll dinic(int s,int t) {
                ll flow = 0;
                while(bfs(s, t)) {
                    while(ll f = dfs(s, t, inff)) flow += f;
                }
                return flow;
            }
int main(){
            int n,m;
            while(~scanf("%d%d", &n, &m)){
                gtot = 0;
                for(int i=0; i<=n+1; i++) head[i]= -1;

                ll sum = 0;
                int s = 0, t = n+1;
                for(int i=1; i<=m; i++) {
                    int u,v,a,b,c;
                    scanf("%d%d%d%d%d", &u, &v, &a, &b, &c);
                    a = a * 2;
                    b = b * 2;
                    c = c * 2;
                    sum += (a + b + c);
                    addedge(s, u, (b + c) / 2);
                    addedge(s, v, (b + c) / 2);
                    addedge(u, t, (a + b) / 2);
                    addedge(v, t, (a + b) / 2);
                    addedge(u, v, (a + c) / 2 - b);
                    addedge(v, u, (a + c) / 2 - b);
                }
                printf("%lld\n", (sum - dinic(s, t)) / 2);
            }
            return 0;
}
View Code

 

2019DX#2

2019DX#2

原文地址:https://www.cnblogs.com/ckxkexing/p/11241597.html