luogu P2462 [SDOI2007]遊戲
還沒人用01BFS?
那我來一發題解。
初始建圖:
方案一:枚舉i,j,暴力判斷
時間複雜度:O(n^2✖26),妥妥地爆炸
方案二:枚舉i,➕或➖一個字母
時間複雜度:O(n*26),可以承受,但是要hush
跑最長路:
方案一:dp 時間複雜度:未知,但會爆
方案二:dijkstra 時間複雜度:O((n+m)logm)但是好像一般
方案三:SPFA沒試過,應該可以水過
方案四:DFS+記憶化
優點:記錄路徑方便
缺點:棧空間小,可能要人工棧
方案五:BFS+記憶化
優點:可以用循環隊列
缺點:記憶路徑有點煩
可以上std了!
std:
#include<bits/stdc++.h>
using namespace std;
const int N=10005,M=105;
const int B=5000005;
struct nody{
int rank;
int len;
}k[N];
struct node{
int u;
int val;
int last;
}q[B];
char s[N][M];
int hav[N][30]={0};
int n=0,cnt=0;
int hed[N],tal[B],nxt[B];
int h=1,t=0;
int H=1,T=0;
int f[N];//f[i]表示到i當前最長路
int maxn=0,p=0;
int maxnnn=0,maxnn=0;
int Q[10000005]={0};
int hushh(int a[]){
int sum=0;
for(int i=1;i<=26;i++){
sum=(sum*108+a[i])%9982445;
}
return sum;
}
inline void addege(int x,int y){
//printf("%d %d\n",x,y);
cnt++;
tal[cnt]=y;
nxt[cnt]=hed[x];
hed[x]=cnt;
}
bool check(int x,int y){
for(int i=1;i<=26;i++){
if(hav[x][i]>hav[y][i]) return 0;
else if(hav[y][i]-hav[x][i]>1) return 0;
}
return 1;
}
inline void print(int x){
for(int i=0;i<strlen(s[x]);i++) printf("%c",s[x][i]);
printf("\n");
}
void dfs(int x){
if(x==-1) return;
dfs(q[x].last);
print(q[x].u);
}
bool cmp(nody x,nody y){
return x.len<y.len;
}
int main(){
//freopen("a.in","r",stdin);
while(~scanf("%s",s[n+1])){
n++;
for(int j=0;j<strlen(s[n]);j++) hav[n][s[n][j]-'a'+1]++;//記錄
}
for(int i=1;i<=n;i++){
for(int j=1;j<=26;j++){
hav[i][j]++;
int esp=Q[hushh(hav[i])];
if(esp!=0) addege(i,esp);
hav[i][j]--;
if(hav[i][j]>0){
//cout << i << " " << j << endl;
hav[i][j]--;
esp=Q[hushh(hav[i])];
if(esp==0){hav[i][j]++;continue;
}
else addege(esp,i);
hav[i][j]++;
}
}
Q[hushh(hav[i])]=i;
}
//接下來:跑個最長路(還要記憶路徑,費力!)
//由於邊權是1,所以跑個01最短路(BFS)
//別慌,有SPJ!
for(int i=1;i<=n;i++){
f[i]=1;
t++;
T++;
q[t].last=-1;
q[t].u=i;
q[t].val=1;
}
while(h<=t){
node u=q[h];
h++;
if(u.val<f[u.u]) continue;
if(u.val>f[u.u]) f[u.u]=u.val;
for(int i=hed[u.u];i;i=nxt[i]){
node v;
v.u=tal[i];
v.last=h-1;
v.val=u.val+1;
if(u.val+1>f[v.u]){
f[v.u]=u.val+1;
t++;
q[t]=v;
}
}
}
for(int i=1;i<=n;i++){
if(f[i]>maxn){
maxn=f[i];
p=i;
}
}
for(int i=t;i>=1;i--){
if(q[i].val==maxn&&q[i].u==p){
p=i;
break;
}
}
printf("%d\n",maxn);
dfs(p);
return 0;
}