2107:Can I go there?
重みなし無向グラフが与えられるので、
1からn駅までz回のステップで行けるかどうか判定する問題。
ただし直前の駅には戻れない。
z回のステップで1からnまで行くパターン数はグラフの隣接行列のn乗。
ノードを(現在の駅,直前の駅)としてグラフの隣接行列を作る。
行列のn乗は繰り返し二乗法を使えばO(m^3logn)で求められる。
#include<iostream> #include<vector> #include<algorithm> using namespace std; typedef vector<int> vec; typedef vector<vec> mat; typedef pair<int,int> P; mat mul(mat &A,mat &B){ mat C(A.size(),vec(B[0].size())); for(int i=0;i<A.size();i++) for(int k=0;k<B.size();k++) for(int j=0;j<B[0].size();j++) C[i][j]+=A[i][k]*B[k][j]; return C; } mat pow(mat A,int n){ mat B(A.size(),vec(A.size())); for(int i=0;i<A.size();i++)B[i][i]=1; for(;n>0;n>>=1){ if(n&1)B=mul(B,A); A=mul(A,A); } return B; } int main(void){ int n,m,z,s,d; while(cin >> n >> m >> z,n|m|z){ vector<P>G; G.push_back(P(1,1)); for(int i=0;i<m;i++){ cin >> s >> d; G.push_back(P(s,d)); G.push_back(P(d,s)); } mat A(G.size(),vec(G.size())); for(int i=0;i<G.size();i++) for(int j=1;j<G.size();j++) if(i!=j && G[i].first!=G[j].second) A[i][j]=G[i].second==G[j].first; A=pow(A,z); bool fg=false; for(int i=0;i<A.size();i++) if(G[i].second==n && A[0][i])fg=true; cout << (fg?"yes":"no") << endl; } return 0; }