[日常训练]嗯哦哎
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;
}