Gym102501G Swapping Places(拓扑排序)

这题十分巧妙的就是对模型的转换。题目给的条件是相邻两个是朋友的物种可以互换。

那么我们发现,我们进行建图,对于我们前面的,如果是自己同一物种的,那么没必要交换

如果是不同物种且不是朋友的,我们没法超越他,这样产生了一个拓扑序。

因为对于前面没有约束的,只需要找到一个字典序最小的输出即可。所以我们设计一个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;
}
View Code

 

posted @ 2020-10-14 22:40  朝暮不思  阅读(152)  评论(0编辑  收藏  举报