P8 ABC209E Shiritori

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

posted @ 2024-05-04 13:57  ComplexityMFC  阅读(3)  评论(0编辑  收藏  举报