zoukankan      html  css  js  c++  java
  • [CF467D] Fedor and Essay

    After you had helped Fedor to find friends in the «Call of Soldiers 3» game, he stopped studying completely. Today, the English teacher told him to prepare an essay. Fedor didn't want to prepare the essay, so he asked Alex for help. Alex came to help and wrote the essay for Fedor. But Fedor didn't like the essay at all. Now Fedor is going to change the essay using the synonym dictionary of the English language.

    Fedor does not want to change the meaning of the essay. So the only change he would do: change a word from essay to one of its synonyms, basing on a replacement rule from the dictionary. Fedor may perform this operation any number of times.

    As a result, Fedor wants to get an essay which contains as little letters «R» (the case doesn't matter) as possible. If there are multiple essays with minimum number of «R»s he wants to get the one with minimum length (length of essay is the sum of the lengths of all the words in it). Help Fedor get the required essay.

    Please note that in this problem the case of letters doesn't matter. For example, if the synonym dictionary says that word cat can be replaced with word DOG, then it is allowed to replace the word Cat with the word doG.

    Input

    The first line contains a single integer m (1 ≤ m ≤ 105) — the number of words in the initial essay. The second line contains words of the essay. The words are separated by a single space. It is guaranteed that the total length of the words won't exceed 105 characters.

    The next line contains a single integer n (0 ≤ n ≤ 105) — the number of pairs of words in synonym dictionary. The i-th of the next n lines contains two space-separated non-empty words xi and yi. They mean that word xi can be replaced with word yi (but not vise versa). It is guaranteed that the total length of all pairs of synonyms doesn't exceed 5·105 characters.

    All the words at input can only consist of uppercase and lowercase letters of the English alphabet.

    Output

    Print two integers — the minimum number of letters «R» in an optimal essay and the minimum length of an optimal essay.

    输入输出样例

    输入样例#1: 
    3
    AbRb r Zz
    4
    xR abRb
    aA xr
    zz Z
    xr y
    
    输出样例#1: 
    2 6
    
    输入样例#2: 
    2
    RuruRu fedya
    1
    ruruRU fedor
    
    输出样例#2: 
    1 10




    十分气愤!!!
    不懂为什么他们机房互模成瘾,实在忍不了。

    我太菜了,这么水的题都想不出来...
    Noip怕是凉了。
    首先我们可以把每个出现的字符串当做一个点,把转化关系当做边。
    用一个pair类型存储每个字符串的$r$的个数和长度。
    然后贪心地想,我们肯定是要让尽可能多的字符串有尽量少的r和尽量少的长度。
    把所有字符串放进队列里bfs,类似spfa,如果能更新的话就再次入队。
    最后所有更新完之后的1——n的r的个数和长度一定是最短的。
    还要注意字符串会有重复,比较坑。
    总之我太菜了。


     
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cstdlib>
    #include <queue>
    #include <map> 
    #include <vector>
    using namespace std;
    #define reg register 
    inline char gc() {
        static const int BS = 1 << 22;
        static unsigned char Buf[BS], *st, *ed;
        if (st == ed) ed = Buf + fread(st = Buf, 1, BS, stdin);
        return st == ed ? EOF : *st++;
    }
    #define gc getchar
    inline int read() {
        int res=0;char ch=getchar();bool fu=0;
        while(!isdigit(ch)) {if(ch=='-')fu=1;ch=getchar();}
        while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=getchar();
        return fu?-res:res;
    }
    #define ll long long
    #define pii pair <ll, ll>
    #define mkp make_pair
    int n, m;
    map <string, int> mp;
    int tot;
    pii memc[600005];
    vector <int> ve[600005];
    ll ans1, ans2; 
    int cp[600005];
    
    inline void down(string &s)
    {
        int len = s.length();
        for (reg int i = 0 ; i < len ; i ++)
            if (s[i] >= 'A' and s[i] <= 'Z') s[i] = s[i] - 'A' + 'a';
    }
    
    inline void add(string &s)
    {
        int len = s.length();
        down(s);
        ll cnt = 0;
        for (reg int i = 0 ; i < len ; i ++)
            if (s[i] == 'r') cnt++;
        if (mp.find(s) == mp.end()) {
            mp[s] = ++tot;
            memc[tot] = mkp(cnt, len);
        }
    }
    
    int main()
    {
        n = read();
        for (reg int i = 1 ; i <= n ; i ++)
        {
            string s;
            cin >> s;
            add(s);
            cp[i] = mp[s];
        }
        m = read();
        for (reg int i = 1 ; i <= m ; i ++)
        {
            string s1, s2;
            cin >> s1 >> s2;
            add(s1), add(s2);
            ve[mp[s2]].push_back(mp[s1]);
        }
        queue <int> q;
        for (reg int i = 1 ; i <= tot ; i ++) q.push(i);
        while (!q.empty())
        {
            int x = q.front();q.pop();
            for (reg int i = 0 ; i < ve[x].size() ; i ++)
            {
                int to = ve[x][i];
                if (memc[to] > memc[x]) {
                    memc[to] = memc[x];
                    q.push(to);
                }
            }
        }
        for (reg int i = 1 ; i <= n ; i ++)
            ans1 += memc[cp[i]].first, ans2 += memc[cp[i]].second;
        printf("%lld %lld
    ", ans1, ans2);
        return 0;
    }
    
    
    


  • 相关阅读:
    SqlBulkCopy 的2篇不错的文章
    xml、json反序列化得到相应的类
    DataTable的使用操作持续更新
    asp.net mvc 添加下拉列表
    asp.net mvc 简单实现权限控制
    ASP.NET 实现上传EXCEL,利用NOPI操作,转换得到DataTable
    asp.net mvc code first 在本地数据库中生成数据库
    第一个随笔
    vb中字母排列组合输出函数
    使用SQL语句查询某表中所有的主键、唯一索引以及这些主键、索引所包含的字段
  • 原文地址:https://www.cnblogs.com/BriMon/p/9702886.html
Copyright © 2011-2022 走看看