题意:输入m个字符串,以及n种关系,这n种关系的两个字符串可以由前面替换为后面,要让原文的r个数最少且最短
题解:这n对关系可以发现是一个有向图,每一个图一个点权(t的个数,长度),直接暴力对原文每一个字符串进行搜索会超时,所以可以在图上搜索,把每一个点更新为最小,要反向更新,所以这里是建反向边
#include <bits/stdc++.h> #define maxn 101000 #define INF 0x3f3f3f3f using namespace std; typedef long long ll; typedef pair<int, int> pii; pii vec[maxn]; ll cnt = 0, ans1, ans2, m, n, c[maxn], t1, t2, dir[maxn]; vector<int>G[maxn]; map<string ,int>mp; string s, s1, s2; ll in[maxn]; ll add(string &s){ ll t = 0; for(ll i=0;i<s.length();i++){ if(s[i]<='Z'&&s[i]>='A') s[i] = s[i]-'A'+'a'; if(s[i] == 'r') t++; } if(!mp.count(s)){ mp[s] = cnt; vec[cnt] = make_pair(t, s.length()); cnt++; } return mp[s]; } void bfs(){ queue<ll >q; for(ll i=0;i<cnt;i++) q.push(i); while(!q.empty()){ ll idx = q.front(); pii u = vec[idx]; q.pop(); for(ll i=0;i<G[idx].size();i++){ ll v = G[idx][i]; if(vec[v] > u){ vec[v] = u; q.push(v); } } } } int main(){ cin>>m; for(ll i=0;i<m;i++) cin>>s, c[i] = add(s); cin>>n; for(ll i=0;i<n;i++){ cin>>s1>>s2; ll a = add(s1); ll b = add(s2); G[b].push_back(a); } bfs(); for(ll i=0;i<m;i++){ ans1 += vec[c[i]].first; ans2 += vec[c[i]].second; } cout<<ans1<<" "<<ans2<<endl; return 0; }