Kejin Game
首先在15年这是一道金牌题(可能现在不是了)
难点在于,没有明确的提示是网络流,想到网络流不一定想到最小割,想到最小割还有会建模
当然这个建模没有那么鬼畜,主要是思路历程要想对。
开始往费用流之类的方向想,都会遇到一个瓶颈
就是流无法解决多对一的关系(所有依赖边小时候才能执行决策2)
所以我们想到了最小割.
具体建模
一些解释
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
const int inf=1e9;
int n,m,s,t,dis[maxn],in[maxn];
struct edge{
int to,nxt,flow;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int flow){
d[++cnt]=(edge){v,head[u],flow},head[u]=cnt;
d[++cnt]=(edge){u,head[v],0},head[v]=cnt;
}
bool bfs()
{
for(int i=0;i<=t;i++) dis[i]=0;
dis[s]=1;
queue<int>q; q.push( s );
while( !q.empty() )
{
int u=q.front(); q.pop();
for(int i=head[u];i;i=d[i].nxt )
{
int v=d[i].to;
if( d[i].flow&&dis[v]==0 )
{
dis[v]=dis[u]+1;
if( v==t ) return true;
q.push( v );
}
}
}
return false;
}
int dinic(int u,int flow)
{
if( u==t ) return flow;
int res=flow;
for(int i=head[u];i&&res;i=d[i].nxt )
{
int v=d[i].to;
if( dis[v]==dis[u]+1&&d[i].flow)
{
int temp=dinic(v,min(res,d[i].flow) );
if( temp==0 ) dis[v]=0;
res-=temp;
d[i].flow-=temp;
d[i^1].flow+=temp;
}
}
return flow-res;
}
signed main()
{
int T; cin >> T;
while( T-- )
{
int z;
cin >> n >> m >> z;
s=0,t=n*2+1;
for(int i=1;i<=m;i++)
{
int l,r,w; cin >> l >> r >> w;
add(l+n,r,w);
}
for(int i=1;i<=n;i++)
{
int x; cin >> x;
add(s,i,x);
}
for(int i=1;i<=n;i++)
{
int x; cin >> x;
add(i,i+n,x);
}
add(z+n,t,inf);
int ans=0;
while( bfs() ) ans+=dinic(s,inf);
cout << ans << endl;
cnt=1;
for(int i=0;i<=t;i++) head[i]=0,in[i]=0;
}
}