[最大流法二分匹配]uva753

9 篇文章 0 订阅

很巧妙的用数组存储c和f方便

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 310;
const int INF = 0x3c3c3c3c;
string str;
map<string,int> rs,dv;
int mr[MAXN];//从源点到i的最小残量
int p[MAXN];//更新时i的上流节点
int c[MAXN][MAXN],f[MAXN][MAXN];
int maxFlow(int op,int ed,int n){
    queue<int>q;
    memset(f,0,sizeof(f));
    memset(p,0,sizeof(p));
    int F=0;
    while(1){
        memset(mr,0,sizeof(mr));
        q.push(op);
        mr[op]=INF;//源点残量
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int v=0;v<n;v++){
                if(!mr[v]&&c[u][v]>f[u][v]){
                    p[v]=u;
                    q.push(v);
                    mr[v]=min(mr[u],c[u][v]-f[u][v]);
                }
            }
        }
        if(mr[ed]==0) return F;
        for(int u=ed;u!=op;u=p[u]){
            f[u][p[u]]-=mr[ed];
            f[p[u]][u]+=mr[ed];
        }
        F+=mr[ed];
    }
}
int main()
{
    int t;
    int n,m,k,did,rid,adt; //adt是多出来的接口数量
    scanf("%d",&t);
    while(t--){
        rs.clear();
        dv.clear();
        memset(c,0,sizeof(c));
        adt=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            cin>>str;
            rs[str]=i;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++){

            cin>>str;
            if((did=dv[str])==0) did=(dv[str]=i);
            c[0][did]+=1;
            cin>>str;
            if((rid=rs[str])==0){
                adt++;
                rid=(rs[str]=n+adt);
            }
            c[did][rid+m]+=1;

        }
        for(int i=m+1;i<=m+n;i++)
            c[i][m+n+adt+1]+=1;
        scanf("%d",&k);
        for(int i=0;i<k;i++){
            cin>>str;
            rid=rs[str];
            cin>>str;
            c[m+rid][m+rs[str]]+=INF;
        }
        int ans=maxFlow(0,m+n+adt+1,m+n+adt+2);
        printf("%d\n",m-ans);
        if(t) puts("");
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值