您的位置:首页 > 其它

解题报告 之 SOJ4429 Frog's Dice

2015-04-14 00:13 246 查看


解题报告 之
SOJ 4429 Frog's Dice

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!


题目大意:Frog神有n个骰子,每个骰子每一面分别有一个字母,然后给你一个字符串,问你能不能用这些骰子拼出这个字符串,每个骰子使用小于等于1次。

分析:明显的二分图匹配,于是乎解决办法就是,设立n个骰子节点,26个字母节点,将超级源点与所有骰子节点连接,负载为INF。将第i个骰子与它每一面对应的字母连上一条负载为1的边。然后数一下字符串里每种字母出现了k次,就在对应的字母节点连一条负载为k的边到超级汇点。

最后看从超级源点到超级汇点的最大流是否==字符串长度l,如果等于则可以组成。那么就上代码了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<string>

using namespace std;

const int MAXN = 1510;
const int MAXM = 200010;
const int INF = 0x3f3f3f3f;

struct Edge
{
    int to, next;
    int cap;
};

Edge edge[MAXM];

int n;
int cnt, src, des;
//cnt表示一共有几条边
int head[MAXN];
//head[i]表示节点i的第一条边的编号
int level[MAXN];
int times[26];

void addedge(int from, int to, int cap)
{
    edge[cnt].to = to;
    edge[cnt].cap = cap;
    edge[cnt].next = head[from];
    head[from] = cnt++;

    edge[cnt].to = from;
    edge[cnt].cap = 0;
    edge[cnt].next = head[to];
    head[to] = cnt++;
}

int bfs()
{
    queue<int> q;
    while (!q.empty())
        q.pop();
    memset(level, -1, sizeof(level));
    level[src] = 0; //源点的深度为0
    q.push(src);

    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if (edge[i].cap > 0 && level[v] == -1) //该边未访问过且该边有流量
            {
                level[v] = level[u] + 1;
                q.push(v);
            }
        }
    }
    return level[des] != -1; //返回是否还存在连通路
}

int dfs(int u, int f)
{
    if (u == des)
        return f;
    int tem;
    for (int i = head[u]; i != -1; i = edge[i].next)
    {
        int v = edge[i].to;
        if (edge[i].cap > 0 && level[v] == level[u] + 1)
        {
            tem = dfs(v, min(f, edge[i].cap));
            if (tem > 0)
            {
                edge[i].cap -= tem;
                edge[i ^ 1].cap += tem; //更新边与反向边的流量
                return tem;
            }
        }
    }
    level[u] = -1; //表示已经走过该点
    return 0;
}

int Dinic()
{
    int ans = 0, tem;
    while (bfs())//如果还存在连通路
    {
        while (tem = dfs(src, INF)) //一直试图寻找增广路
        {
            ans += tem;
        }
    }
    return ans;
}

int main()
{

    int kase;
    scanf("%d", &kase);
    while (kase--)
    {

        char ch;
        scanf("%d", &n);

        cnt = 0;
        memset(head, -1, sizeof(head));
        memset(times, 0, sizeof(times));
        int f, d;
        src = n+26, des = src+1;
        for (int i = 0; i < n; i++)
        {
            addedge(src, i, 1);
        }

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < 6; j++)
            {
                cin >> ch;
                int num = ch - 'a';
                addedge(i, n+num, 1);
            }
        }
        
        string str;
        cin >> str;
        int l = str.length();
        for (int i = 0; i < l; i++)
        {
            times[str[i] - 'a']++;
        }

        for (int i = 0; i < 26; i++)
        {
            if(times[i])
                addedge(n + i, des, times[i]);
        }
        if (str.length() == Dinic())
            cout << "Cong, frog!" << endl;
        else
            cout << "Sorry, frog." << endl;

    }
    return 0;
}


就是这样,反正校赛还是靠大大~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: