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 38 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$的有向边;
- 建图方法二:
答案为$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; }