由于某些字符,会我转为你,你转为他,他转为我,形成一个环,所以先缩点后得到一个DAG森林。
对于森林里的每棵树,做一次取最大值的dp即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=6e5+5;
int n,m,tot,ans1,ans2,id[N],dp1[N],dp2[N],u[N],v[N],nn;
char str[N];
bool vis[N];
int now,top,col,dfn[N],low[N],sta[N],color[N];
struct number{int v,len;}num[N];
map<string,int>mp;
int cnt,head[N];
struct edge{int next,to;}e[N<<1];
inline void add(int u,int v)
{
cnt++;
e[cnt].next=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void tarjan(int u)
{
dfn[u]=low[u]=++now;
sta[++top]=u;
for (register int i=head[u]; i; i=e[i].next)
if (!dfn[e[i].to])
{
tarjan(e[i].to);
low[u]=min(low[u],low[e[i].to]);
}
else if (!color[e[i].to]) low[u]=min(low[u],low[e[i].to]);
if (dfn[u]==low[u])
{
col++;
while (sta[top]!=u)
{
int now=sta[top];
if (num[now].v<dp1[col] || num[now].v==dp1[col] && num[now].len<dp2[col])
dp1[col]=num[now].v,dp2[col]=num[now].len;
color[sta[top]]=col;
top--;
}
int now=sta[top];
if (num[now].v<dp1[col] || num[now].v==dp1[col] && num[now].len<dp2[col])
dp1[col]=num[now].v,dp2[col]=num[now].len;
color[sta[top]]=col;
top--;
}
}
void dfs(int u)
{
if (vis[u]) return;
vis[u]=true;
for (register int i=head[u]; i; i=e[i].next)
{
dfs(e[i].to);
if (dp1[e[i].to]<dp1[u] || dp1[e[i].to]==dp1[u] && dp2[e[i].to]<dp2[u])
dp1[u]=dp1[e[i].to],dp2[u]=dp2[e[i].to];
}
}
signed main(){
int inf=1e18;
for (register int i=1; i<=1e5; ++i) dp1[i]=dp2[i]=inf;
scanf("%lld",&n);
for (register int i=1; i<=n; ++i)
{
scanf("%s",str);
int len=strlen(str);
int now=0;
for (register int j=0; j<len; ++j)
{
if (str[j]>='A' && str[j]<='Z') str[j]=str[j]-'A'+'a';
if (str[j]=='r') now++;
}
int t=mp[str];
if (!t) t=mp[str]=++tot;
num[t].len=len; num[t].v=now;
id[i]=t;
}
scanf("%lld",&m);
while (m--)
{
scanf("%s",str);
int len=strlen(str);
int now=0;
for (register int i=0; i<len; ++i)
{
if (str[i]>='A' && str[i]<='Z') str[i]=str[i]-'A'+'a';
if (str[i]=='r') now++;
}
int x=mp[str];
if (!x) x=mp[str]=++tot;
num[x].len=len; num[x].v=now;
scanf("%s",str);
len=strlen(str);
now=0;
for (register int i=0; i<len; ++i)
{
if (str[i]>='A' && str[i]<='Z') str[i]=str[i]-'A'+'a';
if (str[i]=='r') now++;
}
int y=mp[str];
if (!y) y=mp[str]=++tot;
num[y].len=len; num[y].v=now;
add(x,y);
u[++nn]=x; v[nn]=y;
}
for (register int i=1; i<=tot; ++i) if (!dfn[i]) tarjan(i);
cnt=0; memset(head,0,sizeof(head));
for (register int i=1; i<=nn; ++i)
if (color[u[i]]!=color[v[i]]) add(color[u[i]],color[v[i]]);
for (register int i=1; i<=n; ++i)
{
dfs(color[id[i]]);
ans1+=dp1[color[id[i]]];
ans2+=dp2[color[id[i]]];
}
printf("%lld %lld\n",ans1,ans2);
return 0;
}