洛谷$P$1402 酒店之王 网络流

正解:网络流

解题报告:

传送门!

一看就很网络流昂,,,于是现在的问题就变成怎么建图了$QwQ$

首先如果只有一个要求,那就直接按要求建图然后跑个最大流就好.

现在变成,有两个要求,必须同时满足,考虑怎么解决?

考虑拆点,把人拆成两个点,分别连食物和酒店,然后跑个最大流,做完了$QwQ$

$over$

 

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define lf double
#define gc getchar()
#define t(i) edge[i].to
#define n(i) edge[i].nxt
#define w(i) edge[i].wei
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
#define e(i,x) for(ri i=head[x];~i;i=edge[i].nxt)

const int N=100+5,M=N*20,inf=1e9;
int head[M],ed_cnt=-1,n,p,q,S,T,cur[M],nod_cnt,dep[M];
struct ed{int to,nxt,wei;}edge[M<<1];

il int read()
{
    ri x=0;rb y=1;rc ch=gc;
    while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
    if(ch=='-')ch=gc,y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
    return y?x:-x;
}
il void ad(ri x,ri y,ri z){edge[++ed_cnt]=(ed){x,head[y],z};head[y]=ed_cnt;edge[++ed_cnt]=(ed){y,head[x],0};head[x]=ed_cnt;}
il bool bfs()
{
    queue<int>Q;Q.push(S);memset(dep,0,sizeof(dep));dep[S]=1;
    while(!Q.empty()){ri nw=Q.front();Q.pop();e(i,nw)if(w(i) && !dep[t(i)])dep[t(i)]=dep[nw]+1,Q.push(t(i));}
    return dep[T];
}
il int dfs(ri nw,ri flow)
{
    if(nw==T || !flow)return flow;ri ret=0;
    for(ri &i=cur[nw];~i;i=n(i))if(w(i) && dep[t(i)]==dep[nw]+1){ri tmp=dfs(t(i),min(flow,w(i)));flow-=tmp,w(i)-=tmp,ret+=tmp,w(i^1)+=tmp;}
    return ret;
}
il int dinic(){ri ret=0;while(bfs()){rp(i,S,T)cur[i]=head[i];while(int d=dfs(S,inf))ret+=d;}return ret;}

int main()
{
    memset(head,-1,sizeof(head));n=read();p=read();q=read();
    S=0;T=p+q+(n<<1)+1;rp(i,1,p)ad(i,S,1);rp(i,1,n)ad(i+p+n,i+p,1);rp(i,1,q)ad(T,i+p+(n<<1),1);
    rp(i,1,n)rp(j,1,p){ri tmp=read();if(tmp)ad(i+p,j,1);}rp(i,1,n)rp(j,1,q){ri tmp=read();if(tmp)ad(j+p+(n<<1),i+p+n,1);}
    printf("%d\n",dinic());
    return 0;
}
View Code

 

猜你喜欢

转载自www.cnblogs.com/lqsukida/p/11237055.html
今日推荐