HDU6598 Harmonious Army

经典网络流模型,可以看一下论文(浅析一类最小割问题(pty))
在这里插入图片描述
问 题 转 化 为 所 有 的 贡 献 − 最 小 割 a + b = B + C ( 考 虑 都 在 A 集 合 , 即 花 费 为 B + C ) − − − − − − − ( 1 ) c + d = B + A ( 考 虑 都 在 B 集 合 , 即 花 费 为 B + A ) − − − − − − − ( 2 ) a + d + e = A + C ( 考 虑 一 个 在 A , 一 个 在 B , 即 花 费 为 A + C ) − − ( 3 ) b + c + e = A + C ( 考 虑 一 个 在 A , 一 个 在 B , 即 花 费 为 A + C ) − − ( 4 ) 问题转化为所有的贡献-最小割 \\ a+b = B+C(考虑都在A集合,即花费为B+C) ------- (1)\\ c+d = B+A(考虑都在B集合,即花费为B+A) ------- (2)\\ a+d+e = A+C(考虑一个在A,一个在B,即花费为A+C)--(3)\\ b+c+e = A+C(考虑一个在A,一个在B,即花费为A+C)--(4)\\ a+b=B+C(AB+C)(1)c+d=B+A(BB+A)(2)a+d+e=A+C(ABA+C)(3)b+c+e=A+C(ABA+C)(4)
( 4 ) + ( 3 ) − ( 2 ) − ( 1 ) (4)+(3)-(2)-(1) (4)+(3)(2)(1) 2 e = A + C − 2 B 2e=A+C-2B 2e=A+C2B
考虑一个直观的解
a = b = ( B + C ) / 2 a=b=(B+C)/2 a=b=(B+C)/2
c = d = ( B + A ) / 2 c=d=(B+A)/2 c=d=(B+A)/2
e = ( A + C − 2 B ) / 2 e=(A+C-2B)/2 e=(A+C2B)/2
整体乘2,最后最小割算出来/2即可

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}


const int maxn = 1e3+100;
const int maxm = 1e5+100;
const int inf = 0x7f7f7f7f;

typedef struct Dinic
{
    typedef struct Edge
    {
        int u,v,w,nxt;	
    } Edge;
    int head[maxn],hcnt;
    int dep[maxn];
    int cur[maxn];
    Edge e[maxm];
    int S,T,N;
    void init()
    {
        memset(head,-1,sizeof head);
        hcnt = 0;
        S = T = N = 0;
    }
    void adde(int u,int v,int w)
    {
        e[hcnt].u = u,e[hcnt].v = v,e[hcnt].w = w;
        e[hcnt].nxt = head[u];head[u] = hcnt++;
        e[hcnt].u = v,e[hcnt].v = u,e[hcnt].w = 0;
        e[hcnt].nxt = head[v];head[v] = hcnt++;
    }
    int  bfs()
    {
        rep(i,0,N)
        {
            dep[i] = inf;
        }
        queue<int> q;
        q.push(S); dep[S] = 0;
        while(!q.empty())
        {
            int u = q.front();q.pop();
            for(int i = head[u];~i;i = e[i].nxt)
            {
                int v = e[i].v,w = e[i].w;
                if(w > 0 && dep[u] + 1 < dep[v])
                {
                    dep[v] = dep[u] + 1;
                    if(v == T)
                    {
                        return 1;
                    }
                    q.emplace(v);
                }
            }
        }
        return dep[T] != inf;
    }
    int dfs(int s,int mw)
    {
        if(s == T) return mw;
        for(int i = cur[s];~i;i=e[i].nxt)
        {
            cur[s] = i;
            int v = e[i].v,w=e[i].w;
            if(w <= 0 || dep[v] != dep[s] + 1)
            {
                continue;
            }
            int cw = dfs(v,min(w,mw));
            if(cw <= 0)
                continue;
            e[i].w -= cw;
            e[i^1].w += cw;
            return cw;				
        }
        return 0;
    }
    ll dinic()
    {
        ll res = 0;
        while(bfs())
        {
            rep(i,0,N)
            {
                cur[i] = head[i];
            }
            while(int d = dfs(S,inf))
            {
                res += 1ll * d;
            }
        }
        return res;
    }
}  Dinic;

int n,m,s,t;

ll w[maxn],ww[maxn];
int main(int argc, char const *argv[])
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
    	memset(w,0,sizeof w);memset(ww,0,sizeof ww);
        Dinic din;din.init();
        s = 0,t = n+1;
        din.S = 0,din.T = n+1,din.N = n+10;
       	int u,v;
       	ll a,b,c;
       	ll ans = 0;
       	rep(i,0,m)
       	{	
       		scanf("%d%d%lld%lld%lld",&u,&v,&a,&b,&c);
       		// cout << "---------" << endl;
       		w[u] += b+c;w[v]+=b+c;
       		ww[u] += a+b;ww[v]+=a+b;
       		din.adde(u,v,a+c-2*b);
       		din.adde(v,u,a+c-2*b);
       		ans += a + b + c;
       	}
       	// cout << ans << endl;
       	rep(i,1,n+1)
       	{
       		din.adde(s,i,w[i]);
       		din.adde(i,t,ww[i]);
       	}
        printf("%lld\n",ans-din.dinic()/2 );
    }	
    return 0;
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值