[日常训练]嗯哦哎

Description

$Y$国是一个有$n$座城市,由$m$条双向公路连接起来的国家,任意两个城市至少存在一条路径可以互达。城市与道路都从$1$开始编号。
小$Y$和大$Y$是$Y$国的两位王子,他们今年都来$M$市参加了$NOI$,可惜都打铁滚粗了。

年迈的老$Y$听说了这个消息,想安慰一下两个儿子,于是将两个儿子叫到跟前。

”我想把国家交给你们两个掌管”,老$Y$说道。

”嗯?”,两个儿子诧异。

”我将会把国家分成两部分,两个小国家由你们分别掌管”。老$Y$解释道。

”哦。”两个儿子心领神会,便不多说什么退下了。

”哎!”,老$Y$叹气道。由于$Y$国中每座城市对于两个儿子的支持度不同,所以不同的城市分配给不同儿子会产生不同的价值。并且由于交通方面的关系,如果划分后一条公路归属同一个国家,那么会产生更大的价值,反之这条公路就没有用处,会需要一定代价拆除。

老$Y$算了算,有了如下信息:

  • 现在小$Y$有$1$号城市,大$Y$有$n$号城市,其他城市还没有决定归属。(划分后国家内部的道路可以不连通)。
  • 对于城市$i$,它划分给小$Y$会产生$VA_i$的价值,划给大$Y$会产生$VB_i$的价值。
  • 对于一条路$i$,它如果连接两个小$Y$的城市,会产生$EA_i$的价值;如果连接两个大Y的城市,会产生$EB_i$的价值;否则这条路没有意义将要拆除,会损失$EC_i$的价值。

老$Y$想知道最优的划分方案,你能帮帮他吗?

Input

第一行两个整数$n,m$。表示城市数与道路数。
接下来一行$n-2$个非负整数,表示$VA_i$。
接下来一行$n-2$个非负整数,表示$VB_i$。

接下来$m$行,每行五个非负整数描述一条公路,$x,y,EA_i,EB_i,EC_i$,表示
一条连接$(x,y)$的路。

Output

仅一行一个整数,表示最优划分方案下产生的最大价值。

Sample Input

3 3
8 9
1 2 2 6 2
2 3 8 5 7
1 3 9 4 1

Sample Output

11

HINT

$2;leq;n;leq;10^4,0;leq;m;leq;40000$,价值不超过$2; imes;10^5$.

Solution

  • 建图方法一:

从$s$向$i$连一条容量为$VB_i$的有向边;

从$i$向$t$连一条容量为$VA_i$的有向边;

从$x$向$y$连一条容量为$EC_i$的有向边;

从$y$向$x$连一条容量为$EC_i$的有向边;

从$s$向辅助点$1$连一条容量为$EB_i$的有向边;

从辅助点$1$向$x$连一条容量为$+infty$的有向边;

从辅助点$1$向$y$连一条容量为$+infty$的有向边;

从辅助点$2$向$t$连一条容量为$EA_i$的有向边;

从$x$向辅助点$2$连一条容量为$+infty$的有向边;

从$y$向辅助点$2$连一条容量为$+infty$的有向边;

  • 建图方法二:

image

答案为$sum(VA_i+EA_i+VB_i+EB_i)-$最小割.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 90005 
#define M 680010
#define INF 10000000000ll
using namespace std;
typedef long long ll;
struct graph{
    int nxt,to;ll f;
}e[M];
int g[N],dep[N],n,m,s,t,cnt=1;
ll sum;queue<int> q; 
inline void addedge(int x,int y,ll f){
    e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].f=f;
}
inline void adde(int x,int y,ll f){
    addedge(x,y,f);addedge(y,x,0ll);
}
inline bool bfs(int u){
    memset(dep,0,sizeof(dep));
    q.push(u);dep[u]=1;
    while(!q.empty()){
        u=q.front();q.pop();
        for(int i=g[u];i;i=e[i].nxt)
            if(e[i].f>0&&!dep[e[i].to]){
                q.push(e[i].to);
                dep[e[i].to]=dep[u]+1;
            }
    }
    return dep[t];
}
inline ll dfs(int u,ll f){
    ll ret=0ll,d;
    if(u==t) return f;
    for(int i=g[u];i&&f;i=e[i].nxt)
        if(e[i].f>0&&dep[e[i].to]>dep[u]){
            d=dfs(e[i].to,min(f,e[i].f));
            ret+=d;f-=d;e[i].f-=d;e[i^1].f+=d;
        }
    if(!ret) dep[u]=-1;
    return ret;
}
inline ll dinic(){
    ll ret=0ll;
    while(true){
        if(!bfs(s)) return ret;
        ret+=dfs(s,INF); 
    } 
}
inline void Aireen(){
    scanf("%d%d",&n,&m);
    s=0;t=N-1;
    adde(s,1,0);adde(1,t,INF);
    adde(s,n,INF);adde(n,t,0);
    for(int i=2,k;i<n;++i){
        scanf("%d",&k);
        sum+=(ll)(k);
        adde(i,t,(ll)(k));
    }
    for(int i=2,k;i<n;++i){
        scanf("%d",&k);
        sum+=(ll)(k);
        adde(s,i,(ll)(k));
    }
    for(int i=1,x,y,a,b,c;i<=m;++i){
        scanf("%d%d%d%d%d",&x,&y,&a,&b,&c);
        sum+=(ll)(a+b);
        adde(s,i+n,(ll)(b));
        adde(i+n,x,INF);
        adde(i+n,y,INF);
        adde(x,y,(ll)(c));
        adde(y,x,(ll)(c));
        adde(x,i+n+m,INF);
        adde(y,i+n+m,INF);
        adde(i+n+m,t,(ll)(a));
    }
    printf("%lld
",sum-dinic());
}
int main(){
    freopen("noi.in","r",stdin);
    freopen("noi.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}
原文地址:https://www.cnblogs.com/AireenYe/p/6273603.html