cf 267 div.2 D Fedor and Essay

題目鏈接:http://codeforces.com/contest/467/problem/D

題目描述:給你m 個單詞,n 種替換操作,每種操作有兩個字符串 a b,表示可以將a 替換成 b。然後讓你計算替換之後 的m 個單詞中'r'最少有多少個,在‘r'最少的情況下,m個單詞的總長度最短是多少?(注:單詞不區分大小寫!!!)

解題思路:思路還是比較好想。可以先將n 個替換操作 中的字符串全都hash,然後建一個有向圖,a能被b替換,則由a向b引一條邊,然後跑一邊強連通。在一個強連通分量裏面的點一定可以相互到達,然後縮點,這時候,圖中就沒有環了(這是非常好的),剩下的就是一個記憶化搜索吧(隨便搞一搞就能過。。)

反思,我寫的代碼實在太挫了。。。代碼太長

另外,圖論太差了。。。真心不懂那些算法,只會敲版。。。還要多練

//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 500005;
const int MAXN = 500010;
vector<int> link[MAXN];
int mem[MAXN], stk[MAXN], depth[MAXN];
int sum, num;
bool mark[MAXN], used[MAXN];

void dfs(int k, int deep)
{
    int min, i;
    min = depth[k] = deep;
    used[k] = 1;
    stk[sum++] = k;
    for (i = 0; i < link[k].size(); i++)
    {
        if (mark[link[k][i]]) continue;
        if (!used[link[k][i]]) dfs(link[k][i], deep + 1);
        if (min > depth[link[k][i]]) min = depth[link[k][i]];
    }
    if (depth[k] > min)
    {
        depth[k] = min;
        return;
    }
    while (stk[sum - 1] != k)
    {
        mem[stk[sum - 1]] = num;
        mark[stk[sum - 1]] = 1;
        sum--;
    }
    mark[k] = 1;
    mem[k] = num;
    sum--;
    num++;
}

map<string,int> mp;
char str[N];
string s[N];
string pt[N<<1];
int cnt[N][2];
map<pair<int,int>,int> mpp;
vector<int> v[N];
bool vis[N];

void dfs_ans(int k)
{
    vis[k]=true;
    int sz=v[k].size();
    int length=cnt[k][0],cntr=cnt[k][1];
    for(int i=0;i<sz;i++)
    {
        int to=v[k][i];
        if(!vis[to]) dfs_ans(to);
        int len=cnt[to][0],r=cnt[to][1];
        if(r<cntr)
        {
            cntr=r,length=len;
        }else if(r==cntr&&len<length)
        {
            length=len;
        }
    }
    cnt[k][0]=length,cnt[k][1]=cntr;
}

void calc(string t,int &r,int &len)
{
    len=t.size();
    r=0;
    for(int i=0;i<len;i++) if(t[i]=='r') r++;
}

int main()
{
#ifdef PKWV
    freopen("in.in", "r", stdin);
#endif // PKWV
    int m;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        scanf("%s",str);
        for(int j=0;str[j];j++) str[j]|=0x20;
        s[i]=str;
    }
    int n;
    scanf("%d",&n);
    int lx=1;
    for(int i=0;i<n;i++)
    {
        scanf("%s",str);
        for(int j=0;str[j];j++) str[j]|=0x20;
        string t=str;
        int t1=mp[t];
        if(t1==0)
        {
            pt[lx]=t;
            t1=mp[t]=lx++;
        }
        scanf("%s",str);
        for(int j=0;str[j];j++) str[j]|=0x20;
        t=str;
        int t2=mp[t];
        if(t2==0)
        {
            pt[lx]=t;
            t2=mp[t]=lx++;
        }
        link[t1].PB(t2);
    }
    for(int i=1;i<lx;i++)
    {
        if(!used[i]) dfs(i,0);
    }
    for(int i=1;i<lx;i++)
    {
        int t=mem[i];
        int r,len;
        calc(pt[i],r,len);
        if(cnt[t][0]==0)
        {
            cnt[t][0]=len,cnt[t][1]=r;
        }
        else
        {
            if(r<cnt[t][1])
            {
                cnt[t][1]=r,cnt[t][0]=len;
            }else if(cnt[t][1]==r&&len<cnt[t][0])
            {
                cnt[t][0]=len;
            }
        }
    }
    int ly=1;
    for(int i=1;i<lx;i++)
    {
        int t=mem[i];
        int sz=link[i].size();
        for(int j=0;j<sz;j++)
        {
            int tt=mem[link[i][j]];
            if(t==tt) continue;
            if(mpp[make_pair(t,tt)]==0)
            {
                v[t].PB(tt);
                mpp[make_pair(t,tt)]=ly++;
            }
        }
    }
    for(int i=1;i<lx;i++)
    {
        if(!vis[mem[i]])
        {
            dfs_ans(mem[i]);
        }
    }
    int ct=0;
    ll len=0;
    for(int i=0;i<m;i++)
    {
        if(mp[s[i]])
        {
            int t=mem[mp[s[i]]];
            len+=cnt[t][0],ct+=cnt[t][1];
        }else
        {
            int sz=s[i].size();
            for(int j=0;j<sz;j++) if(s[i][j]=='r') ct++;
            len+=sz;
        }
    }
    printf("%d %I64d\n",ct,len);
    return 0;
}


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