http://poj.org/problem?id=3281
题意:
多种饮料和食物,多种牛,每种牛可以在它喜欢的饮料和食物中选一种。三者都只能用一次,求最大满足牛的数量。
解析:
最大流构造:
- 饮料和食物只能用一次,那么连源点到饮料,食物到汇点,容量1
- 饮料和食物需要牛连接,饮料到牛,牛到食物
- 牛只能用一次,牛拆成两个点,之间容量为1
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=550,M=40001;
int n,f,D;
int head[N],nex[M],to[M],val[M],now;
void add(int a,int b,int v){
to[++now]=b;val[now]=v;nex[now]=head[a];head[a]=now;
to[++now]=a;val[now]=0;nex[now]=head[b];head[b]=now;
}
//*********************
int sp,ep,d[N];
int bfs(){
queue<int>Q;
memset(d,-1,sizeof(d));
d[sp]=0;
Q.push(sp);
while(!Q.empty()){
int p=Q.front();Q.pop();
for(int i=head[p];~i;i=nex[i]){
int u=to[i];
if(d[u]==-1&&val[i]>0){
d[u]=d[p]+1;
Q.push(u);
}
}
}
return d[ep]!=-1;
}
int dfs(int p,int v){
int r=0;
if(p==ep)return v;
for(int i=head[p];(~i)&&r<v;i=nex[i]){
int u=to[i];
if(val[i]>0&&d[u]==d[p]+1){
int x=dfs(u,min(val[i],v-r));
r+=x;
val[i]-=x;
val[i^1]+=x;
}
}
if(!r)d[p]=-2;
return r;
}
int dinic(){
int ans=0,t;
while(bfs()){
while(t=dfs(sp,inf))ans+=t;
}
return ans;
}
//***********************
void init(){
now=-1;//要求第一条边为0
memset(head,-1,sizeof(head));
}
int main(){
init();
scanf("%d%d%d",&n,&f,&D);
for(int i=1;i<=f;i++)add(0,i,1);
for(int i=1;i<=D;i++)add(i+300,401,1);
for(int i=1;i<=n;i++){
add(i+100,i+200,1);
int nf,nd;scanf("%d%d",&nf,&nd);
for(int j=1,tmp;j<=nf;j++)scanf("%d",&tmp),add(tmp,i+100,1);
for(int j=1,tmp;j<=nd;j++)scanf("%d",&tmp),add(i+200,tmp+300,1);
}
sp=0,ep=401;
int ans=dinic();
printf("%d\n",ans);
}
http://acm.hdu.edu.cn/showproblem.php?pid=2732
题意:
n*m地图上,有很多柱子,已经很多蜥蜴,蜥蜴可以跳到曼哈顿距离小于等于d的柱子上。柱子有一个耐久度,当一只蜥蜴从这个柱子上跳走时,耐久度-1,为0时不能有蜥蜴跳到上面。
蜥蜴跳出地图则获救,问最少还有几只蜥蜴留下。
解析:
首先是源点到蜥蜴健一条1的,然后要控制每个点走过的数量,点拆成两个点控制。点和点之间建,点到地图外(汇点)建。
//hdu 2732 最大流
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1001,M=40001;
int head[N],nex[M],to[M],val[M],now;
void add(int a,int b,int v){
to[++now]=b;val[now]=v;nex[now]=head[a];head[a]=now;
to[++now]=a;val[now]=0;nex[now]=head[b];head[b]=now;
}
//*********************
int sp,ep,d[N];
int bfs(){
queue<int>Q;
memset(d,-1,sizeof(d));
d[sp]=0;
Q.push(sp);
while(!Q.empty()){
int p=Q.front();Q.pop();
for(int i=head[p];~i;i=nex[i]){
int u=to[i];
if(d[u]==-1&&val[i]>0){
d[u]=d[p]+1;
Q.push(u);
}
}
}
return d[ep]!=-1;
}
int dfs(int p,int v){
int r=0;
if(p==ep)return v;
for(int i=head[p];(~i)&&r<v;i=nex[i]){
int u=to[i];
if(val[i]>0&&d[u]==d[p]+1){
int x=dfs(u,min(val[i],v-r));
r+=x;
val[i]-=x;
val[i^1]+=x;
}
}
if(!r)d[p]=-2;
return r;
}
int dinic(){
int ans=0,t;
while(bfs()){
while(t=dfs(sp,inf))ans+=t;
}
return ans;
}
//***********************
void init(){
now=-1;//要求第一条边为0
memset(head,-1,sizeof(head));
}
char Mp[21][21];
int V[21][21];
int id1(int i,int j){
return (i-1)*21+j;
}
int id2(int i,int j){
return 450+(i-1)*21+j;
}
int main(){int t;int ca=0;cin>>t;while(t--){
sp=0,ep=450;
init();
int n,m,d;
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++)scanf("%s",Mp[i]+1);
m=strlen(Mp[1]+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
V[i][j]=Mp[i][j]-'0';
if(V[i][j])add(id1(i,j),id2(i,j),V[i][j]);
}
}
int All=0;
for(int i=1;i<=n;i++)scanf("%s",Mp[i]+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(Mp[i][j]=='L'){
All++;
add(0,id1(i,j),1);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(!V[i][j])continue;
for(int k=-d;k<=d;k++){
for(int h=abs(k)-d;h<=d-abs(k);h++){
int x=i+k,y=j+h;
if(x<=0||y<=0||x>n||y>m)add(id2(i,j),450,V[i][j]);
else if(V[x][y]){
add(id2(i,j),id1(x,y),V[i][j]);
}
}
}
}
}
int ans=dinic();
if(ans==All)printf("Case #%d: no lizard was left behind.\n",++ca);
else if(All-ans==1)printf("Case #%d: %d lizard was left behind.\n",++ca,1);
else printf("Case #%d: %d lizards were left behind.\n",++ca,All-ans);
}}