P8 ABC209E Shiritori

ComplexityMFC發表於2024-05-04

ABC209 - E Shiritori

​ 真是場酣暢淋漓的戰鬥呵...

​ 首先,這道題並不算難,主要是邏輯要清晰,思路要完整,心態別爆炸。(de了一個晚上沒de出來...)

NO1. 轉圖

​ 首先這題一定是圖論題。

​ 由於可能出現重複的單詞,所以考慮用map標記,並用vector儲存答案對應的圖中節點下標,比較容易。同時可以使用類似雜湊的方式記錄首三位字母和末三位字母的出現節點,最後掃一遍,一一連線即可。

NO2. 勝負態博弈

​ 這題關鍵之一在於想到如何轉化。其實也很套路,由於不可能每一個點都跑一邊 \(dfs\), 然後又存在環,亂七八糟的。所以另有它法:發現對於一個沒有出度的點,選擇它必贏,而如果一個點連向一個必敗態的點,那麼這個點必贏,因為連過去可以導致對方處於必敗態。

​ 於是乎,可以考慮倒著建圖,把出度為 \(0\) 變為入度為 \(0\), 考慮能否轉化。

​ 這和拓撲實在是太像了,但是問題是存在該死的環。

NO3. 解環

​ 有環並非無解。

​ 如果 \(Takahashi\) 選了個環上的點,而這個點連向必敗態的點,那麼 \(Takahashi\) 就會輸。所以如果一個環,其中有些點存在轉為對手必敗態的選項,那麼這個環是假環。

​ 由於每個人都不想輸,所以如果一個點它連向了必勝態的點,會讓對手贏,那麼它一定不會先考慮走這個點。於是乎真環是存在的,當且僅當環上所有的點都不存在轉為對手必敗態的選項。

​ 所以在拓撲時並非只有入度為零時才把點加入佇列。當然,每個點應該只走一次,因為每一步都是正確的,所以再走一次也是徒勞(環),而且會導致入度為負,造成誤判。

碼子:

#define pb push_back

const int N=250010;

bool vis[N];
string s[N];
map<string,int> mp;
int n,_in[N],status[N];
vector<int> v[N],G[N],ans;

inline void Add(int x,int y)
{ G[x].pb(y);}

inline void solve(){
	memset(status,-1,sizeof(status));//平局態
	queue<int> q;
	for(int i=1;i<=n;++i) if(!_in[i]){
		q.push(i);
		status[i]=1;//takahashi在此為必勝態
	}
	while(q.size()){
		int x=q.front(); q.pop();
		if(vis[x]) continue; vis[x]=true;
		if(status[x]==-1) status[x]=1;//如果是這種情況,那麼說明該點所連點全是必勝態,則該點為必勝態
		for(int to:G[x]){
			_in[to]--;
			if(status[x]) status[to]=0,q.push(to);//ok
			else if(!_in[to]) q.push(to);
		}
	}
	for(int i:ans){
		if(status[i]==0) cout<<"Aoki\n";
		else cout<<(status[i]<0?"Draw":"Takahashi")<<'\n';
	}
}

int main(){
  IOS
  cin>>n;
  for(int i=1;i<=n;++i){
      cin>>s[i]; int sl=s[i].length();
      string t={s[i][0],s[i][1],s[i][2],s[i][sl-3],s[i][sl-2],s[i][sl-1]};
      if(mp[t]){
          --i,--n;
          ans.pb(mp[t]);
          continue;
      } mp[t]=i,ans.pb(mp[t]);
      v[(s[i][0]-'A')+(s[i][1]-'A')*60+(s[i][2]-'A')*60*60].pb(i);
  }
	
  for(int i=1;i<=n;++i){
      int sl=s[i].length();
      for(int x:v[(s[i][sl-3]-'A')+(s[i][sl-2]-'A')*60+(s[i][sl-1]-'A')*60*60])
          Add(x,i),_in[i]++;
  }
  solve();
  return 0;
}

NO4. Extra

​ 有些圖是不存在的?? 比如: (只有有向邊)

1 2
2 3
3 1
2 5
3 4
4 5

​ 兩個輔助debug資料:

21 okies hmerc kgsyk vywge cuagc ibxgk ndzma agcic kgsoki agcndz ndzagc cuaagc agckgs agcndz ndzvyw ndzcua agcndz cuandz agccua ndzibx kgsoki
其中:16,19:Takahashi
16 wewnv disak sqowk zcybm adaqw audis ngbva kcqgs audwew adadis ngbsqo ngbzcy audada audaud audzcy wewada
其中:14:Draw

​ · EOF

相關文章