川大oj 4429

題目大意:給你n個骰子,骰子每面是一個字母,最後給你一個串,讓你每個骰子只能用一次時,能否組合成所給的串

解題思路:比賽的時候我們想的建一個二分圖,跑二分匹配,這個思路是沒有錯的,但二分匹配跑超時了,自己就沒更加深入的思考,因爲自己覺得二分匹配時能夠跑過的,當時改的相當冒火。最後下來題解說二分匹配是能夠過的(自己的二分匹配太挫),自己用網絡流過的,建圖思想:將每個骰子與自己有的字母連起來,將給的串的字母與匯點連起來,起點與沒給骰子連起來,每個邊的容量都爲1,然後跑一次最大流即可,詳見代碼

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
#define mmax 30005
#define inf 99999999

char s[1005];
int used[2005][30];
struct node
{
    int flow;
    int en;
    int next;
}E[mmax];
int p[mmax];
int num;
void init()
{
    memset(p,-1,sizeof p);
    num=0;
}
void add(int st,int en,int flow)
{
    E[num].en=en;
    E[num].flow=flow;
    E[num].next=p[st];
    p[st]=num++;
    E[num].en=st;
    E[num].flow=0;
    E[num].next=p[en];
    p[en]=num++;
}
bool vis[mmax];
int d[mmax];
int cur[mmax];
bool bfs(int st,int en)
{
    memset(vis,0,sizeof vis);
    d[st]=0;
    vis[st]=1;
    queue<int>q;
    q.push(st);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=p[x]; i+1; i=E[i].next)
        {
            int v=E[i].en;
            if(!vis[v]&&E[i].flow)
            {
                vis[v]=1;
                d[v]=d[x]+1;
                q.push(v);
            }
        }
    }
    return vis[en];
}
int dfs(int st,int en,int  flow)
{
    if(st==en||flow==0)
        return flow;
    int f=0,dd;
    for(int &i=cur[st]; i+1;i=E[i].next)
    {
        int v=E[i].en;
        if(d[st]+1==d[v]&&(dd=dfs(v,en,min(flow,E[i].flow)))>0)
        {
            E[i].flow-=dd;
            E[i^1].flow+=dd;
            flow-=dd;
            f+=dd;
            if(flow==0)
                break;
        }
    }
    return f;
}
int dinic(int st,int en,int nn)
{
    int flow=0;
    while(bfs(st,en))
    {
        for(int i=0;i<=nn;i++)
            cur[i]=p[i];
        flow+=dfs(st,en,inf);
    }
    return flow;
}
int main()
{
    int T;
    scanf("%d",&T);
    int n;
    char c;
    while(T--)
    {
        init();
        scanf("%d",&n);
        memset(used,0,sizeof(used));
        for(int i=1;i<=n;i++)
        {
            for(int k=0;k<6;k++)
            {
                getchar();
                c=getchar();
                if(!used[i+26][c-'a'+1])
                {
                    add(i+26,c-'a'+1,1);
                    used[i+26][c-'a'+1]=1;
                    //printf("%d->%d ",i+26,c-'a'+1);

                }
            }
            //printf("\n");
            add(0,i+26,1);
        }
        scanf("%s",s);
        int len=strlen(s);
        for(int i=0;i<len;i++)
        {
            add(s[i]-'a'+1,27+n,1);
            //printf("->%d ",s[i]-'a'+1);
        }
        //printf("\n");
        int ans=dinic(0,n+27,n+27);
        //printf("%d\n",ans);
        if(ans==len)
        puts("Cong, frog!");
        else
        puts("Sorry, frog.");
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章