【XSY1552】自動機 構造
題目大意
給你一個自動機,包含\(n\)個狀態,指令集為前\(m\)個小寫字母,對於每個狀態\(s\)和每個指令\(i\),自動機均有後繼\(T(s,i)\)。請你求出一個長度不超過\(2^{20}\)的指令序列,使得無論自動機當前處在哪個狀態(包括初始狀態),按順序執行指令序列的所有指令後,自動機都處於初始狀態\(1\)。無解輸出\([impossible]\)
\(1\leq n\leq 100,1\leq m\leq 26\)
題解
首先要證明一個結論:原問題有解等價於對於任意狀態\(i\),都存在一個指令序列\(S_i\)使得\(T(s,S_i)=1\)且\(T(1,S_i)=1\)
必要性顯然。如果不存在\(S_i\),那麽狀態\(i\)和狀態\(1\)一定不可能同時轉移到狀態\(1\)。
對於充分性,我們考慮所有當前可能的狀態集合\(U\)。一開始\(U=\{1,2,3\ldots n\}\)。每次我們任選\(U\)中一個狀態\(t\),執行\(S_t\)。這樣我們會得到一個集合\(U‘\),滿足\(1\in U‘\)且\(|U‘|<|U|\)。這樣我們經過若幹步後可以得到\(U=\{1\}\)。我們把所有\(S_t\)連在一起得到一個指令序列\(S\),易證\(S\)是滿足要求的。
所以我們每次任選\(U\)中的一個狀態\(t\),求出\(S_t\)
對於狀態\(i\),求\(S_i\)的時間復雜度是\(O(n^2)\)的,執行\(S_i\)是\(O(n^3)\)的,總共要執行\(O(n)\)次,所以時間復雜度是\(O(n^4)\)的。
每個\(S_i\)的長度是\(O(n^2)\)的,總共要執行\(O(n)\)次,所以答案的長度是\(O(n^3)\)的
代碼
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int a[110][30];
int n,m;
char s[10000010];
int cnt;
int c[110];
int d[110];
int vis[110][110];
int st[10010];
int top;
int dfs(int x,int y)
{
if(x==1&&y==1)
return 1;
vis[x][y]=1;
int i;
for(i=1;i<=m;i++)
{
int lx=a[x][i];
int ly=a[y][i];
if(!vis[lx][ly])
{
st[++top]=i;
if(dfs(lx,ly))
return 1;
top--;
}
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
a[i][j]++;
}
cnt=0;
for(i=1;i<=n;i++)
c[i]=i;
int now=n;
while(now>1)
{
memset(vis,0,sizeof vis);
top=0;
if(!dfs(1,c[2]))
{
printf("[impossible]");
return 0;
}
for(i=1;i<=top;i++)
{
s[++cnt]=st[i]+‘a‘-1;
for(j=1;j<=now;j++)
c[j]=a[c[j]][st[i]];
}
sort(c+1,c+now+1);
now=unique(c+1,c+now+1)-c-1;
}
s[cnt+1]=‘\0‘;
printf("%s\n",s+1);
return 0;
}
【XSY1552】自動機 構造