洛谷P1231 教辅的组成(网络流)

### 洛谷P1231 题目链接 ###

题目大意:每本书里面有对应的习题册和答案册,但是现在封面已经模糊不清了,只能判断出默写习题册可能属于某本书,而某些答案册可能属于某本书。给出两种所属的所有可能性,判断出最大可能地组合成一本完整的书的本数。

 

分析:

此题是三种物品间的匹配问题,建图需要将三种物品的容量全限制为 1 即可。与之前的 洛谷P1402  一样的做法,注意数组的大小。

代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define maxn 40008
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
queue<int> Q;
int n,p,q,cnt,S,T;
int head[maxn],cur[maxn],d[maxn];
struct Edge{
    int to;
    int val;
    int next;    
}edge[maxn<<2];
inline void add(int u,int v,int w){
    edge[++cnt].to=v;
    edge[cnt].val=w;
    edge[cnt].next=head[u];
    head[u]=cnt;
    return;
}
bool bfs(){
    while(!Q.empty()) Q.pop();
    memset(d,-1,sizeof(d));
    d[S]=0;
    Q.push(S);
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(d[v]==-1&&edge[i].val>0){
                d[v]=d[u]+1;
                Q.push(v);
            }
        }
    }
    return d[T]!=-1;
}
int dfs(int u,int flow){
    int nowflow=0;
    if(u==T) return flow;
    for(int i=cur[u];~i;i=edge[i].next){
        cur[u]=i;
        int v=edge[i].to;
        if(d[v]==d[u]+1&&edge[i].val>0){
            if(int k=dfs(v,min(flow-nowflow,edge[i].val))){
                edge[i].val-=k;
                edge[i^1].val+=k;
                nowflow+=k;
                if(nowflow==flow) break;
            }
        }
    }
    if(!nowflow) d[u]=-1;
    return nowflow;
}
int Dinic(){
    int ans=0;
    while(bfs()){
        for(int i=0;i<=T;i++) cur[i]=head[i];
        ans+=dfs(S,inf); 
    }
    return ans;
}
int main()
{
    scanf("%d%d%d",&n,&p,&q);
    int t,A,B;
    cnt=-1;
    memset(head,-1,sizeof(head));
    S=0,T=2*n+p+q+1;
    for(int i=1;i<=p;i++) add(S,i,1),add(i,S,0);
    for(int i=1;i<=q;i++) add(p+2*n+i,T,1),add(T,p+2*n+i,0);
    for(int i=1;i<=n;i++) add(p+i,p+n+i,1),add(p+n+i,p+i,0);
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d%d",&A,&B);
        add(B,p+A,1),add(p+A,B,0);
    }
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        scanf("%d%d",&A,&B);
        add(p+n+A,p+2*n+B,1),add(p+2*n+B,p+n+A,0);
    }
    printf("%d\n",Dinic());
}

猜你喜欢

转载自www.cnblogs.com/Absofuckinglutely/p/12219063.html
今日推荐