标签:cout 思考 fir queue span build turn 第一个 mpp
思考了挺久的一题,主要卡在建图这一块,序列上的问题很难想到图论上。。
可以交换位置是一种关系,那么不能交换也是一种关系:两个不是朋友的点,相对位置保持不变!
不能交换的关系的两点就可以连边,在图上u->v就表示u一定在v前面
但是这样暴力建图显然会炸,我们再进行优化:
我们把动物i(设物种x)和其后面第一个物种也是x的点连边,那么每个点只要考虑其后面每种物种的第一个动物即可,那么每个点最多连200条边(想想为什么)
用序列自动机预处理一下+建图就好了
#include<bits/stdc++.h> using namespace std; #define N 100005 #define mk make_pair vector<string>v; int s,l,n,a[N],g[205][206]; map<string,int>mp; map<int,string>mpp; int nxt[N][205],pos[205],in[N]; vector<int>G[N]; void build(){ for(int i=1;i<=s;i++)pos[i]=n+1; for(int i=n;i>=1;i--){ for(int j=1;j<=s;j++) nxt[i][j]=pos[j]; pos[a[i]]=i; } for(int i=1;i<=n;i++){ for(int j=1;j<=s;j++) if(nxt[i][j]!=n+1 && !g[a[i]][j]){ G[i].push_back(nxt[i][j]); in[nxt[i][j]]++; } } } priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>> >q; int ans[N],tp,vis[N]; void topsort(){ for(int i=1;i<=n;i++)if(in[i]==0)q.push(mk(a[i],i)); while(q.size()){ int u=q.top().second; ans[++tp]=q.top().first; q.pop(); for(auto vv:G[u]){ in[vv]--; if(in[vv]==0)q.push(mk(a[vv],vv)); } } } int cmp(string a,string b){ int res=a.compare(b); return res<0; } int main(){ //freopen("test07.in","r",stdin); cin>>s>>l>>n; for(int i=1;i<=s;i++){ string s;cin>>s; v.push_back(s); } sort(v.begin(),v.end(),cmp); for(int i=0;i<v.size();i++){ mp[v[i]]=i+1,mpp[i+1]=v[i]; //cout<<v[i]<<" "<<mp[v[i]]<<‘\n‘; } for(int i=1;i<=l;i++){ string a,b;cin>>a>>b; int u=mp[a],v=mp[b]; //cout<<u<<" "<<v<<‘\n‘; g[u][v]=g[v][u]=1; } for(int i=1;i<=n;i++){ string s;cin>>s; a[i]=mp[s]; //cout<<s<<" "<<mp[s]<<"\n"; } build(); topsort(); for(int i=1;i<=n;i++)cout<<mpp[ans[i]]<<" "; }
【建图】【思维】拓扑排序建图+序列自动机——swerc Gym - 102501G 好题
标签:cout 思考 fir queue span build turn 第一个 mpp
原文地址:https://www.cnblogs.com/zsben991126/p/13122345.html