UVA - 753 A Plug for UNIX(二分图最大匹配/最大流)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a54665sdgf/article/details/80699482

题目大意:给你n个插座和m个插头,插头只能插到相同类型的插座上,让你求最少剩多少个不能匹配的插头(就是插头总数-匹配的个数)。另外给你k种转换器,每种转换器均有无限多个,一种插头插上某种类型的转换器之后即可变成另一种插头,一个插头可以连接多个转换器。

思路:这道题可以用朴素的二分图匹配,用Floyed算法判定每种插头与每种插座是否能够匹配。也可以用网络流的方法,把源点s与每个插头连一条边,容量为插头个数,同样把每个插座与汇点t连一条边,容量为插座个数;对每种转换器,如果插头u能转化为插头v,则把u与v连一条容量为无穷大的边。从源点s到汇点t的最大流即为所求。

注意:每种插头与插座的名称均为字符串,需要用map将其转化为整数编码。

用网络流的方法似乎更快些,我用二分图匹配的方法花了50ms,而网络流的花费为0ms,这大概是BFS相对于DFS的优势所在吧QAQ。

如果以后还有新的方法,我会再次更新。

二分图匹配代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#define FRER() freopen("i.txt","r",stdin)
using namespace std;
const int N=100+10;
const int M=4*N;
int nID;
map<string,int> mp;
int ID(char* s)
{
    if(mp.count(s))
        return mp[s];
    return mp[s]=nID++;
}
int device[N],target[N],n,m,trans[M][M],vis[N],op[N];
void Floyed()
{
    for(int k=0; k<nID; ++k)
        for(int i=0; i<nID; ++i)
            for(int j=0; j<nID; ++j)
                trans[i][j]|=trans[i][k]&trans[k][j];
}
bool match(int u)
{
    for(int v=0; v<n; ++v)
    {
        if(!trans[device[u]][target[v]]||vis[v])
            continue;
        vis[v]=1;
        if(op[v]==-1||match(op[v]))
        {
            op[v]=u;
            return true;
        }
    }
    return false;
}
int main()
{
    //FRER();
    int T;
    scanf("%d",&T);
    while(T--)
    {
        mp.clear();
        nID=0;
        char s1[26],s2[26];
        scanf("%d",&n);
        for(int i=0; i<n; ++i)
        {
            scanf("%s",s1);
            target[i]=ID(s1);
        }
        scanf("%d",&m);
        for(int i=0; i<m; ++i)
        {
            scanf("%*s%s",s1);
            device[i]=ID(s1);
        }
        memset(trans,0,sizeof trans);
        for(int i=0; i<nID; ++i)
            trans[i][i]=1;
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s%s",s1,s2);
            trans[ID(s1)][ID(s2)]=1;
        }
        Floyed();
        int ans=0;
        memset(op,-1,sizeof op);
        for(int i=0; i<m; ++i)
        {
            memset(vis,0,sizeof vis);
            if(match(i))
                ++ans;
        }
        printf("%d\n",m-ans);
        if(T)
            printf("\n");
    }
    return 0;
}

网络流代码:(我一开始想用mp.size()+2代替total,但是交上去WA,本地运行没有错,大概是兼容问题)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#define FRER() freopen("i.txt","r",stdin)
using namespace std;
const int INF=0x3f3f3f3f;
const int N=400+10;
int cap[N][N],d[N],p[N],total;
map<string,int> mp;
int ID(char* s)
{
    if(mp.count(s))
        return mp[s];
    return mp[s]=total++;
}
int EK(int s,int t)
{
    int flow=0;
    queue<int> q;
    while(1)
    {
        memset(d,0,sizeof d);
        q.push(s);
        d[s]=INF;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int v=0; v<total; ++v)
            {
                if(!d[v]&&cap[u][v])
                {
                    p[v]=u;
                    d[v]=min(d[u],cap[u][v]);
                    q.push(v);
                }
            }
        }
        if(!d[t])
            break;
        flow+=d[t];
        for(int u=t; u!=s; u=p[u])
        {
            cap[p[u]][u]-=d[t];
            cap[u][p[u]]+=d[t];
        }

    }
    return flow;
}
int main()
{
    //FRER();
    int T;
    scanf("%d",&T);
    while(T--)
    {
        total=2;
        mp.clear();
        char s1[26],s2[26];
        int n,cnt;
        scanf("%d",&n);
        memset(cap,0,sizeof cap);
        while(n--)
        {
            scanf("%s",s1);
            ++cap[ID(s1)][1];
        }
        scanf("%d",&n);
        cnt=n;
        while(n--)
        {
            scanf("%*s%s",s1);
            ++cap[0][ID(s1)];
        }
        scanf("%d",&n);
        while(n--)
        {
            scanf("%s%s",s1,s2);
            cap[ID(s1)][ID(s2)]=INF;
        }
        printf("%d\n",cnt-EK(0,1));
        if(T)
            printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a54665sdgf/article/details/80699482