这题十分巧妙的就是对模型的转换。题目给的条件是相邻两个是朋友的物种可以互换。
那么我们发现,我们进行建图,对于我们前面的,如果是自己同一物种的,那么没必要交换
如果是不同物种且不是朋友的,我们没法超越他,这样产生了一个拓扑序。
因为对于前面没有约束的,只需要找到一个字典序最小的输出即可。所以我们设计一个last数组表示每个物种最近出现的位置
如果不是朋友就连边,之后做一遍优先队列拓扑即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int N=1e5+10; const int inf=0x3f3f3f3f; const int M=2e7; int in[N],h[M],ne[M],e[M],idx; struct node{ int id; int k; bool operator <(const node &t) const{ return k>t.k; } }g[N]; string s[N]; int st[300][300],n; map<string,int> m1; int last[N]; int ans[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void topo(){ int i; priority_queue<node> q; for(i=1;i<=n;i++){ if(!in[i]) q.push(g[i]); } int cnt=0; while(q.size()){ auto t=q.top(); q.pop(); ans[++cnt]=t.k; for(int i=h[t.id];i!=-1;i=ne[i]){ int j=e[i]; in[j]--; if(!in[j]){ q.push(g[j]); } } } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int i; int S,L; cin>>S>>L>>n; for(i=1;i<=S;i++) cin>>s[i]; sort(s+1,s+1+S); for(i=1;i<=S;i++){ m1[s[i]]=i; } memset(last,-1,sizeof last); for(i=1;i<=L;i++){ string a,b; cin>>a>>b; st[m1[a]][m1[b]]=st[m1[b]][m1[a]]=1; } for(i=1;i<=n;i++){ string a; cin>>a; g[i].id=i,g[i].k=m1[a]; for(int j=1;j<=S;j++){ if(last[j]==-1||st[g[i].k][j]) continue; add(last[j],i); in[i]++; } last[g[i].k]=i; } topo(); for(i=1;i<=n;i++){ cout<<s[ans[i]]<<" "; } cout<<endl; }