【USACO】New Years Party
时间:2020-08-05 14:28:24
收藏:0
阅读:79
题意描述
\(N(3\leq N\leq 200)\) 头奶牛举办新年聚会。每头奶牛会做几种不同的佳肴(以“碟”记数)。
一共有 \(D(5\leq D\leq 100)\) 种菜肴,依次以 \(1\) 到 \(D\) 的数字标记。
大家希望聚会上的菜肴数量越多越好,但是同种菜肴的数量有一个上限。
每头奶牛可以带 \(K\) 碟菜肴 \((1\leq K\leq 5)\) ,但必须都是不同的菜肴。
求聚会上最多可能有多少碟菜肴?
算法分析
闲话
一开始以为是什么神仙 贪心 或 DP,结果撑死推不出 DP 柿子,又口胡不了贪心...。
经 dalao 点拨之后发现网络流模型是真的难看出来。
建图
建立一个超级源点连接 \(1\)~\(n\) 号节点(表示 \(1\)~\(n\) 号奶牛),边权为 \(k\)。
若 \(i\) 号奶牛会做 \(j\) 号菜,就连接 \(edge(i,j+n)\),边权为 \(1\)。
建立一个超级汇点连接 \(1+n\)~\(d+n\) 号节点(表示 \(1\)~\(d\) 号菜),边权为每种菜的数量上限。
网络流
然后就是 Dinic 的板子了(据说 EK 会 T)。
代码实现
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#define N 210
#define D 110
#define M 5000010
#define INF 0x3f3f3f3f
using namespace std;
int n,kk,dd,s,t,head[N+D],cnt=1;
struct Edge{
int nxt,to,val;
}ed[M];
queue<int>q;
int read(){
int x=0,f=1;char c=getchar();
while(c<‘0‘ || c>‘9‘) f=(c==‘-‘)?-1:1,c=getchar();
while(c>=‘0‘ && c<=‘9‘) x=x*10+c-48,c=getchar();
return x*f;
}
void add(int u,int v,int w){
ed[++cnt].nxt=head[u];
ed[cnt].to=v;
ed[cnt].val=w;
head[u]=cnt;
ed[++cnt].nxt=head[v];
ed[cnt].to=u;
ed[cnt].val=0;
head[v]=cnt;
return;
}
int d[N+D];
bool bfs(){
memset(d,0,sizeof(d));
while(!q.empty()) q.pop();
q.push(s);d[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=head[u];i;i=ed[i].nxt){
int v=ed[i].to,w=ed[i].val;
if(w && !d[v]){
d[v]=d[u]+1;
if(v==t) return true;
q.push(v);
}
}
}
return false;
}
int dinic(int u,int flow){
if(u==t) return flow;
int rest=flow;
for(int i=head[u];i && rest;i=ed[i].nxt){
int v=ed[i].to,w=ed[i].val;
if(w && d[v]==d[u]+1){
int k=dinic(v,min(rest,w));
if(!k) d[v]=0;
ed[i].val-=k;
ed[i^1].val+=k;
rest-=k;
}
}
return flow-rest;
}
int main(){
//freopen("party.in","r",stdin);
//freopen("party.out","w",stdout);
n=read(),kk=read(),dd=read();
s=0,t=n+dd+1;
int a,b;
for(int i=1;i<=dd;i++)
a=read(),add(i+n,t,a);
for(int i=1;i<=n;i++){
a=read();
for(int j=1;j<=a;j++)
b=read(),add(i,b+n,1);
}
for(int i=1;i<=n;i++) add(s,i,kk);
int ans=0,flow;
while(bfs())
if(flow=dinic(s,INF)) ans+=flow;
printf("%d\n",ans);
//fclose(stdin);fclose(stdout);
return 0;
}
完结撒花。
原文:https://www.cnblogs.com/lpf-666/p/13439389.html
评论(0)