CodeForces

题目链接:http://codeforces.com/problemset/problem/467/D

题意:一篇文章(不分大小写)有n个单词,有m个替换方式,后面的单词可以变成前面的单词,问文章在出现字母r最少的情况下,长度最短。

输出r的数量和长度。

思路:贪心的思路,将每个单词用最少的r单词替代,r数相同时就选长度最小。这里是用bfs来完成贪心。

处理:用map<string,int>mp把单词(字符串)编号,用编写的结构体s数值保存长度和r的数量。

用vector<int>v[]储存可以代替的单词编号。

用bfs搜索每一个单词下s符合条件的情况

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#define inf 0x3f3f3f3f
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;

struct node{
    int len;
    int sumr;
}s[2*maxn],p;//s存储编号后,该编号单词可表示最少r数下最短的。 
int tot,n,m,flag[maxn];
map<string, int>mp;
vector<int> v[maxn*2];//存编号后,该编号可以代替的单词编号 

void cl(string& str)//单词处理,将单词编号,并记录其s数组下的值 
{
    int len=str.length();
    int cnt=0;
    for(int i=0;i<len;i++)
    {
        if('A'<=str[i]&&str[i]<='Z')//统一转化成小写字母 
            str[i]=str[i]-'A'+'a';
        if(str[i]=='r')//记录'r'的数量 
            cnt++;
    }
    if(!mp.count(str))//找没出现的单词 
    {
        mp[str]=tot;//tot为编号 
        s[tot].len=len;//记录该编号的长度及r数量 
        s[tot++].sumr=cnt;
    }
}

void bfs()//广搜,将每个s代表的单词变成可以表示的最少r数是最短 
{
    queue<int> q;
    for(int i=0;i<tot;i++)
        q.push(i);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        p=s[t];
        int len=v[t].size();
        for(int i=0;i<len;i++)//和每个可转换单词比较 
        {
            int x=v[t][i];
            if(p.sumr<s[x].sumr)//r数量更少 
            {
                s[x].sumr=p.sumr;
                s[x].len=p.len;
                q.push(x);
            }
            else if(p.sumr==s[x].sumr&&s[x].len>p.len)//r数量相同,长度更短 
            {
                s[x].len=p.len;
                q.push(x);
            }
        }
    }
}

int main()
{
    cin>>n;
    string str1,str2;
    for(int i=0;i<n;i++)
    {
        getchar();
        cin>>str1;
        cl(str1);
        flag[i]=mp[str1];//记录每个单词的编号 
    }
    cin>>m;
    for(int i=0;i<m;i++)
    {
        cin>>str1>>str2;
        cl(str1);
        cl(str2);
        v[mp[str2]].push_back(mp[str1]);//可以取代,用编号表示 
    }
    bfs();//搜索后每个s的单词都是最小 
    ll sum=0,len=0;
    for(int i=0;i<n;i++)//求答案 
    {
        sum+=s[flag[i]].sumr;
        len+=s[flag[i]].len;
    }
    cout<<sum<<" "<<len<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/xiongtao/p/9916944.html