Union_of_Britain
2024-04-16 13:28:43
一个
字典序最小,则从前往后选能选的最小的。
现在压力给到如何判定。容易想到网络流判定,但是看上去每次判定一下复杂度有点爆炸。那么先尝试从后往前构造一组合法解。根据 CF1168E 的想法,考虑根据后面的解来调整。
具体来说,当前
那么这个
注意到我只关心两个事情:这个路径上的位置可以做这样的替换,并且最后
这样的图怎么构造呢?对于每个已经确定为 unordered_set
。找到这样的路径之后,修改图即可。修改量是单次
最后构造答案时类似地动态判定即可。需要注意的是后面不能挪用前面的(时代的抉择)。
这样我们就使用更优的复杂度解决了这道题。
很史的考场代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int cur[maxn],sze[6],n,m,alo[maxn][7],vis[6],can[6];
char s[maxn];
unordered_set<int> d[6][6];
#define VI vector<int>
VI CUR;
bool dfs(int u,int t){
if(u==t)return 1;
vis[u]=1;
for(int i=0;i<6;i++){
if(vis[i])continue;
if(d[u][i].size()){
CUR.push_back(i);
if(dfs(i,t))return 1;
CUR.pop_back();
}
}
return 0;
}
void DFS(int u){
can[u]=1;
for(int i=0;i<6;i++){
if(can[i])continue;
if(d[i][u].size())DFS(i);
}
}
VI findpath(int u,int v){
CUR={u};
for(int i=0;i<6;i++)vis[i]=0;
if(dfs(u,v))return CUR;
return {};
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>s+1;n=strlen(s+1);
cin>>m;
for(int i=1;i<=m;i++){
int k;string s2;
cin>>k>>s2;
for(auto u:s2)alo[k][u-'a']=1;
alo[k][6]=1;
}
for(int i=1;i<=n;i++){
if(!alo[i][6])for(int j=0;j<6;j++)alo[i][j]=1;
}
for(int i=1;i<=n;i++)sze[s[i]-'a']++;
for(int i=n;i>=1;i--){
bool flg=0;
for(int j=0;j<6;j++){
if(!sze[j])continue;
if(alo[i][j]){
sze[j]--;cur[i]=j;
for(int k=0;k<6;k++)if(alo[i][k]&&j!=k)d[j][k].insert(i);
flg=1;break;
}
VI F;
for(int k=0;k<6;k++)can[k]=0;
DFS(j);
for(int k=0;k<6;k++){
if(j!=k&&can[k]&&alo[i][k]){
F=findpath(k,j);
int t[7];
for(int i=0;i<F.size()-1;i++)t[i]=(*d[F[i]][F[i+1]].begin()),sze[F[i]]++,sze[F[i+1]]--;
for(int i=0;i<F.size()-1;i++){
cur[t[i]]=F[i+1];
for(int l=0;l<6;l++)if(alo[t[i]][l]&&l!=F[i+1])d[F[i+1]][l].insert(t[i]);
for(int l=0;l<6;l++)if(alo[t[i]][l]&&l!=F[i])d[F[i]][l].erase(t[i]);
}
sze[k]--;
cur[i]=k;
for(int l=0;l<6;l++)if(alo[i][l]&&l!=k)d[k][l].insert(i);
flg=1;
break;
}
}
if(flg)break;
}
if(!flg)return cout<<"Impossible"<<endl,0;
}
for(int i=1;i<=n;i++){
for(int j=0;j<6;j++)if(alo[i][j]&&j!=cur[i])d[cur[i]][j].erase(i);
int res=-1;
for(int k=0;k<6;k++)can[k]=0;
DFS(cur[i]);
for(int j=0;j<cur[i];j++){
if(!alo[i][j]||!can[j])continue;
VI F=findpath(j,cur[i]);
int t[7];
for(int i=0;i<F.size()-1;i++)t[i]=(*d[F[i]][F[i+1]].begin());
for(int i=0;i<F.size()-1;i++){
cur[t[i]]=F[i+1];
for(int l=0;l<6;l++)if(alo[t[i]][l]&&l!=F[i+1])d[F[i+1]][l].insert(t[i]);
for(int l=0;l<6;l++)if(alo[t[i]][l]&&l!=F[i])d[F[i]][l].erase(t[i]);
}
res=j;
break;
}
if(res==-1)res=cur[i];
cur[i]=res;
cout<<(char)(res+'a');
}
return 0;
}