[日常训练]嗯哦哎

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\;\times\;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\)的有向边;

建图方法二:

答案为\(\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\n",sum-dinic());
}
int main(){
    freopen("noi.in","r",stdin);
    freopen("noi.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}
posted @ 2017-01-11 14:42  Aireen_Ye  阅读(355)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.