题目链接:
题意:
给定n个单词。
以下有m个替换方式。左边的单词能变成右边的单词。
替换随意次后使得最后字母r个数最少,在r最少的情况下单词总长度最短
输出字母r的个数和单词长度。
思路:
我们觉得一个单词有2个參数。则m个替换规则能够当成m个点的有向图。
则某些单词的替换终点会确定,所以反向建图bfs一下。
为了防止某些点被重复更新,所以把每一个点的权值都放到栈里排个序然后bfs。
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<map> #include<string> using namespace std; typedef int ll; const int inf = 1000000; #define N 300005 int n, m; void go(string &x){ int len = x.length(); for(int i = 0; i < len; i++) if('A' <= x[i] && x[i] <= 'Z') x[i] = x[i]-'A'+'a'; } string s[N], a[N], b[N]; int S[N], A[N], B[N], LEN[N], NUM[N]; map<string, int> mp; struct Edge{ int to, nex; }edge[N*10]; int head[N], edgenum; void init(){memset(head, -1, sizeof head); edgenum = 0;} void add(int u, int v){ Edge E = {v, head[u]}; edge[edgenum] = E; head[u] = edgenum++; } struct node{ int x, y, point; node (int X = 0, int Y = 0, int P = 0):x(X), y(Y), point(P){} bool operator<(const node&D){ if(D.x!=x)return D.x > x; return D.y>y; } }st[N], dis[N]; int top; bool cmp(node X, node Y){ if(X.x != Y.x) return X.x < Y.x; if(X.y != Y.y) return X.y < Y.y; return X.point < Y.point; } int tot; void BFS(int x){ queue<int>q; q.push(x); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; ~i; i = edge[i].nex){ int v = edge[i].to; if(dis[u] < dis[v]) { dis[v] = dis[u]; q.push(v); } } } } void input(){ mp.clear(); init(); top = tot = 0; for(int i = 1; i <= n; i++) { cin>>s[i]; go(s[i]); if(mp.count(s[i])==0) { S[i] = mp[s[i]] = ++tot; int len = s[i].length(), num = 0; for(int j = 0; j < len; j++) num += s[i][j]=='r'; st[top++] = node(num, len, tot); LEN[tot] = len; NUM[tot] = num; } else S[i] = mp[s[i]]; } scanf("%d", &m); for(int i = 1; i <= m; i++) { cin>>a[i]>>b[i]; go(a[i]); go(b[i]); if(mp.count(a[i])==0) { A[i] = mp[a[i]] = ++tot; int len = a[i].length(), num = 0; for(int j = 0; j < len; j++) num += a[i][j]=='r'; st[top++] = node(num, len, tot); LEN[tot] = len; NUM[tot] = num; } else A[i] = mp[a[i]]; if(mp.count(b[i])==0) { B[i] = mp[b[i]] = ++tot; int len = b[i].length(), num = 0; for(int j = 0; j < len; j++) num += b[i][j]=='r'; st[top++] = node(num, len, tot); LEN[tot] = len; NUM[tot] = num; } else B[i] = mp[b[i]]; add(B[i], A[i]); } } int main(){ while(~scanf("%d", &n)){ input(); for(int i = 1; i <= tot; i++)dis[i] = node(NUM[i], LEN[i],0); sort(st, st+top, cmp); for(int i = 0; i < top; i++) BFS(st[i].point); long long ans1 = 0, ans2 = 0; for(int i = 1; i <= n; i++) ans1 += dis[S[i]].x, ans2 += dis[S[i]].y; printf("%I64d %I64d\n", ans1, ans2); } return 0; }