SCU 4429 frog's dice (二分匹配 or 网络流)

题目链接

4429: frog's dice

Submit your solution     Discuss this problem     Best solutions

Time: 2000ms

The Problem

frog has many dices:)
Each dice has six surfaces and there is a lowercase letter on each surfaces.
Now, frog want to put these dices in a row so that the letters on the upper faces could form a certain word.
She can put these dices in any order but each dice can only be used once.
Please tell frog whether she could make that thing happen.?

Input

The first line of input is the number of test case.

Then for each case:
The first line is a number n(1 <= n <= 1000), indicating the number of dices.
Then there are n lines, each line has six lowercase letters(separated by space), indicating the letters on a dice.
The last line has n lowercase letters, indicating frog's special word.

Output

For each case, print one line:
If frog can get her special word, print "Cong, frog!"(without quotation);
else print "Sorry, frog."

Example Input

2
3
s c u a c m
a b c d e f
a b c d e f
scu
4
a e c f a c
d z b g f a
p r j a a a
h e t g o a
frog

Example Output

Sorry, frog.
Cong, frog!

Author

frog

题意:有n个6面的骰子,每个面上都有一个字母。现在有一个长度为n的字符串,问把这个n个骰子摆成一排,能否构成这个字符串??

题解:一个骰子可以摆出多种字母,一个字母可以被多个骰子表示,但是一个骰子只能摆出一个字母。很容易看出是个二分匹配。但是用匈牙利算法求解要超时。

用Hopcroft-Karp 算法才能过。二分图的左边n个点表示n个骰子,右边n个字母表示字符串,假若一个骰子能表示某个字母,则在这个骰子和字符串直接建边。

当然也可以用网络流来做这题,并且用网络流可以把右边n个点换成24个点(分别表示24个字母)。

二分匹配代码如下:

#include<cstdio>
#include<cstring>
#include<set>
#include<iostream>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<cctype>
#include<algorithm>
#define inf 0x3fffffff
#define nn 1100
#define mod 1000000007
typedef long long LL;
using namespace std;
int n;
char a[nn][6];
char s[nn];
struct node
{
    int en,next;
}E[nn*nn];
int p[nn],num;
void init()
{
    memset(p,-1,sizeof(p));
    num=0;
}
void add(int st,int en)
{
    E[num].en=en;
    E[num].next=p[st];
    p[st]=num++;
}
int mx[nn*2],my[nn*2];
queue<int>que;
int dx[nn*2],dy[nn*2];
bool vis[nn*2];
bool Find(int u)
{
    int i,w;
    for(i=p[u];i+1;i=E[i].next)
    {
        w=E[i].en;
        if(!vis[w]&&dy[w]==dx[u]+1)
        {
            vis[w]=true;
            if(!my[w]||Find(my[w]))
            {
                mx[u]=w;
                my[w]=u;
                return true;
            }
        }
    }
    return false;
}
int matching()
{
    memset(mx,0,sizeof(mx));
    memset(my,0,sizeof(my));
    int ans=0;
    int w;
    while(true)
    {
        bool flag=false;
        while(!que.empty())
            que.pop();
        memset(dx,0,sizeof(dx));
        memset(dy,0,sizeof(dy));
        for(int i=1;i<=n;i++)
        {
            if(!mx[i])
                que.push(i);
        }
        while(!que.empty())
        {
            int u=que.front();
            que.pop();
            for(int i=p[u];i+1;i=E[i].next)
            {
                w=E[i].en;
                if(!dy[w])
                {
                    dy[w]=dx[u]+1;
                    if(my[w])
                    {
                        dx[my[w]]=dy[w]+1;
                        que.push(my[w]);
                    }
                    else
                        flag=true;
                }
            }
        }
        if(!flag)
            break;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            if(!mx[i]&&Find(i))
                ans++;
        }
    }
    return ans;
}
int main()
{
    int t,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        getchar();
        for(i=0;i<n;i++)
        {
            scanf("%c %c %c %c %c %c",&a[i][0],&a[i][1],&a[i][2],&a[i][3],&a[i][4],&a[i][5]);
            getchar();
        }
        scanf("%s",s);
        init();
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                for(k=0;k<6;k++)
                {
                    if(a[i][k]==s[j])
                    {
                        add(i+1,j+n+1);
                        break;
                    }
                }
            }
        }
        if(matching()==n)
            puts("Cong, frog!");
        else
            puts("Sorry, frog.");
    }
    return 0;
}

网络流代码如下:

#include<cstdio>
#include<cstring>
#include<set>
#include<iostream>
#include<map>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
#include<cctype>
#include<algorithm>
#define inf 0x3fffffff
#define nn 1100
#define mod 1000000007
typedef long long LL;
using namespace std;
int n;
char a[nn][6];
char s[nn];
struct node
{
    int en,next,len;
}E[nn*nn];
int p[nn],num;
void init()
{
    memset(p,-1,sizeof(p));
    num=0;
}
void add(int st,int en,int len)
{
    E[num].en=en;
    E[num].next=p[st];
    E[num].len=len;
    p[st]=num++;

    E[num].en=st;
    E[num].next=p[en];
    E[num].len=0;
    p[en]=num++;
}
int dis[nn];
int que[nn];
int tp[nn];
bool bfs()
{
    memset(dis,-1,sizeof(dis));
    int top,pop;
    top=pop=0;
    dis[0]=0;
    que[pop++]=0;
    int sta,w,i;
    while(top<pop)
    {
        sta=que[top++];
        for(i=p[sta];i+1;i=E[i].next)
        {
            w=E[i].en;
            if(E[i].len&&dis[w]==-1)
            {
                dis[w]=dis[sta]+1;
                if(w==n+27)
                    return true;
                que[pop++]=w;
            }
        }
    }
    return false;
}
int dfs(int id,int flow)
{
    if(id==n+27)
        return flow;
    int w,ix;
    int re=0;
    int &i=tp[id];
    for(;i+1;i=E[i].next)
    {
        w=E[i].en;
        if(dis[w]==dis[id]+1&&E[i].len)
        {
            ix=dfs(w,min(flow,E[i].len));
            if(ix)
            {
                E[i].len-=ix;
                E[i^1].len+=ix;
                flow-=ix;
                re+=ix;
                if(flow==0)
                    break;
            }
        }
    }
    return re;
}
int dinic()
{
    int i,re=0;
    while(bfs())
    {
        for(i=0;i<=n+27;i++)
            tp[i]=p[i];
        re+=dfs(0,inf);
    }
    return re;
}
int use[30];
int main()
{
    int t,i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        getchar();
        init();
        memset(use,0,sizeof(use));
        for(i=0;i<n;i++)
        {
            add(0,i+1,1);
            scanf("%c %c %c %c %c %c",&a[i][0],&a[i][1],&a[i][2],&a[i][3],&a[i][4],&a[i][5]);
            getchar();
        }
        scanf("%s",s);
        for(i=0;i<n;i++)
            use[s[i]-'a'+1]++;
        for(i=1;i<=26;i++)
        {
            if(use[i])
                add(n+i,n+27,use[i]);
        }
        for(i=0;i<n;i++)
        {
            for(j=0;j<6;j++)
            {
                add(i+1,a[i][j]-'a'+1+n,1);
            }
        }
        if(dinic()==n)
            puts("Cong, frog!");
        else
            puts("Sorry, frog.");
    }
    return 0;
}



你可能感兴趣的:(ACM,图论,二分匹配,网络流)