problem
Description
Input
Output
Sample Input
4 2 1
1 2 3 1
2 3 1 2
1 2 3
1 3 2
2 0 100 1 2
Sample Output
108
Data Constraint
analysis
正解网络流,做法也是听完讲才会的
既然题目要求最大收益,那么意思就是总收益亏得最少
最小割
首先从极源 S S 向到 n n 的点各连上流量的边, 1 1 到的点向极汇 T T 连上流量的边
对于规律一,从 i i 到和从 j j 到之间*连上流量为 k k 的双向边
对于规律二,如果是牛,新建一个节点,从源点连向新建节点一条无穷大流量的边,从新建节点连向集合里面所有的点一条流量为 b b 的边;如果是羊,集合里每个点连向新建节点(流量为),再从新建节点流向汇点 T T <script type="math/tex" id="MathJax-Element-2299">T</script>(流量无穷大)
最后总收益减掉最小割(最大流)就是答案
code
#include<bits/stdc++.h>
#define MAXN 1000001
#define INF 1000000007
using namespace std;
int last[MAXN],next[MAXN],tov[MAXN],odd[MAXN],cur[MAXN];
int a[MAXN],b[MAXN],depth[MAXN];
int n,m,k,S,T,tot=1,ans;
int read()
{
int x=0,f=1;
char ch=getchar();
while (ch<'0' || '9'<ch)
{
if (ch=='-')f=-1;
ch=getchar();
}
while ('0'<=ch && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int min(int x,int y)
{
return x<y?x:y;
}
void insert(int x,int y,int z)
{
next[++tot]=last[x];
last[x]=tot;
tov[tot]=y;
odd[tot]=z;
next[++tot]=last[y];
last[y]=tot;
tov[tot]=x;
odd[tot]=0;
}
bool bfs()
{
queue<int> que;
while (!que.empty())que.pop();
memset(depth,0,sizeof(depth));
depth[S]=1;
que.push(S);
while (!que.empty())
{
int now=que.front();
que.pop();
for (int i=last[now];i;i=next[i])
{
int j=tov[i];
if (odd[i]>0 && depth[j]==0)
{
depth[j]=depth[now]+1;
que.push(j);
}
}
}
if (depth[T]==0)return 0;
return 1;
}
int dfs(int now,int flow)
{
if (now==T)return flow;
int ans=0;
for (int i=cur[now];i;i=next[i])
{
if (depth[tov[i]]==depth[now]+1 && odd[i])
{
int temp=dfs(tov[i],min(flow-ans,odd[i]));
if (!temp)depth[tov[i]]=0;
ans+=temp;
odd[i]-=temp,odd[i^1]+=temp;
if (ans==flow)break;
}
}
return ans;
}
int dinic()
{
int ans=0;
while (bfs())
{
memcpy(cur,last,sizeof(last));
while (int x=dfs(S,INF))ans+=x;
}
return ans;
}
int main()
{
freopen("work.in","r",stdin);
freopen("work.out","w",stdout);
//freopen("readin.txt","r",stdin);
n=read()+1,m=read(),k=read();
S=0,T=n;
for (int i=1;i<n;i++)
{
int x=read();
ans+=x;
insert(S,i,x);
}
for (int i=1;i<n;i++)
{
int x=read();
ans+=x;
insert(i,T,x);
}
for (int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
insert(x,y,z),insert(y,x,z);
}
for (int i=1;i<=k;i++)
{
int x=read(),y=read(),z=read();
n++,ans+=z;
(y==0)?insert(S,n,z):insert(n,T,z);
while (x--)(y==0)?insert(n,read(),INF):insert(read(),n,INF);
}
printf("%d\n",ans-dinic());
return 0;
}