千手观音(天梯赛)

比赛的时候被前面的题目心态搞崩了 时间就不够了 就一个简单的拓扑排序 唉 真可惜了

首先对行字符串从前往后建边就好 对于上下两个具有相同前缀的字符串 首先必须两者大小相同

之后就对第一个不同的字符串建边就好

最后因为要字典序最小 用优先队列就好

#include <bits/stdc++.h>
using namespace std;
map<string, int> mp;
string S[10010];
vector<vector<string> > vs;
vector<string> ts;

int main() { 
	int n;
	cin >> n;
	string s;	
	int idx = 0;
	for(int i = 0; i < n; ++ i) {
		cin >> s;
		s += ".";
		string t = "";
		ts.clear();
		for(int j = 0; j < (int)s.size(); ++ j) {
			if(s[j] == '.') {
				ts.push_back(t);
				if(!mp.count(t)) { 
					mp[t] = ++ idx;
					S[idx] = t;
				}
				t = "";
			}
			else t += s[j];
		}
		vs.push_back(ts);
	}	
	vector<vector<int> > G(idx + 1);
	vector<int> d(idx + 1);
	for(int i = 1; i < n; ++ i) {
		if(vs[i].size() == vs[i - 1].size()) {
			for(int j = 0; j < (int)vs[i].size(); ++ j) {
				if(vs[i][j] != vs[i - 1][j]) {
					int x = mp[vs[i - 1][j]], y = mp[vs[i][j]];
					G[x].push_back(y);
					d[y] ++;
					break;
				}
			}
		}
	}
	priority_queue<string, vector<string>, greater<string> > q;
	int ok = 1;
	for(int i = 1; i <= idx; ++ i) 
		if(d[i] == 0) 
			q.push(S[i]);
	while(!q.empty()) {
		string u = q.top();
		if(ok) {
            cout << u;
            ok = 0;
        }
        else cout << "." << u;
		q.pop();
		for(int i=0;i<G[mp[u]].size();i++) {
			int v=G[mp[u]][i];
			d[v] --;
			if(d[v] == 0) {
				q.push(S[v]);
			}
		} 
	}
	return 0;
}

posted @ 2022-04-28 20:41  wzx_believer  阅读(91)  评论(0)    收藏  举报