I - Magic Potion ( 网络最大流 )
题意:n个人, m个怪兽 ,k个buff。 接下来n行代表第i个人可以杀的怪兽编号, 每个人只能杀一只怪兽,但是如果有buff就可以杀两只怪兽,但是每个人只能用一次buff。 问最多能杀多少只怪兽。
思路:网络流, s源点连接n个人流量为1(代表每个人只能杀一只怪兽),每只怪兽连接汇点t流量为1( 代表每只怪兽只能被杀一次 ), 人和其能杀死的怪兽连接流量为1 , 跑一遍denic,得到不用buff的答案。 我们再假设这里的每个人都拿到了一个buff,所以s到相邻点的流量都变成1, 再跑一遍dinic, 这样如果跑出来的二次答案大于buff的数量那么所有buff都能贡献一个答案, 如果小于, 那么答案就是一次答案加二次答案。
代码:
#include <iostream> // 网络最大流
#include <queue>
#include <stdio.h>
#include <cstring>
#include <map>
#define inf 0x3f3f3f3f
using namespace std;
struct node {
int to,w,nxt;
};
const int maxn = 2e5+10;
node e[maxn];
int n,m,s,t,k;
int head[maxn];
int dep[maxn];
int cnt;
void addage( int u, int v, int w )
{
e[cnt].to = v;
e[cnt].w = w;
e[cnt].nxt = head[u];
head[u] = cnt++;
}
int bfs(int node) // bfs分层
{
memset(dep,0,sizeof(dep)); // dep 层的深度
dep[node] = 1;
queue <int> Q;
Q.push(node);
while ( !Q.empty() ) {
int x = Q.front();Q.pop();
for ( int i=head[x]; i!=-1; i=e[i].nxt ) {
int y = e[i].to,w = e[i].w;
if ( !dep[y] && w ) {
dep[y] = dep[x] + 1; // 编号++
Q.push(y);
}
}
}
return dep[t]; // return dep[t] , 如果是0那么说明没有增广路了,退出while
}
int dfs( int x, int flow ) // dfs找增广路
{
if ( x==t ) {
return flow;
}
int sum = 0;
for ( int i=head[x]; i!=-1; i=e[i].nxt ) {
int y = e[i].to, w = e[i].w;
if ( w && dep[y]==dep[x]+1 ) {
int t = dfs(y,min(flow,w));// 注意dfs里面的是min(flow,w)
flow -= t; // 当前的flow减t
sum+=t; // sum加t,就是上面减去的t。
e[i].w -= t; // 正向边减t
e[i^1].w += t; // 反向边加t
}
}
if ( sum==0 ) { // 如果sum==0,那么这个点之前没有增广路,深度清零
dep[x] = 0;
}
return sum;
}
int main()
{
int i,j,x;
memset(head,-1,sizeof(head));
cnt=0;
// 人 1-500, 怪兽500+i,
s = 0; t = 1010;
scanf("%d %d %d",&n,&m,&k);
for ( i=1; i<=n; i++ ) {
addage(s,i,1);
addage(i,s,0);
int tt;
scanf("%d",&tt);
for ( j=1; j<=tt; j++ ) {
scanf("%d",&x);
addage(i,500+x,1);
addage(500+x,i,0);
}
}
for ( i=1; i<=m; i++ ) {
addage( 500+i,t,1 );
addage( t,500+t,0 );
}
int ans = 0;
while ( bfs(s) ) { // 如果还存在增广路继续
ans += dfs(s,0x3f3f3f3f); // 加一条增广路的值
}
for ( i=head[s]; i!=-1; i=e[i].nxt ) {
e[i].w = 1;
}
int tot = 0;
while ( bfs(s) ) { // 如果还存在增广路继续
tot += dfs(s,0x3f3f3f3f); // 加一条增广路的值
}
if ( tot>=k ) {
ans += k;
}
else {
ans += tot;
}
printf("%d\n",ans);
return 0;
}
/*
5 10 2
2 3 10
5 1 3 4 6 10
5 3 4 6 8 9
3 1 9 10
5 1 3 6 7 10
*/
转载自原文链接, 如需删除请联系管理员。
原文链接:I - Magic Potion ( 网络最大流 ),转载请注明来源!