您的位置:首页 > Web前端

cf 267 div.2 D Fedor and Essay

2014-09-19 15:05 465 查看
题目链接: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
;
string s
;
string pt[N<<1];
int cnt
[2];
map<pair<int,int>,int> mpp;
vector<int> v
;
bool vis
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: