Problem 2107 : Can I go there?

問題概要

日本語なので略。
本文参照(http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=2107&lang=jp

解法

現在どのノードにいるか、直前にどのノードにいたかを(i,j)とあらわす。
この状態数は辺の数×2になる。


(辺×2)×(辺×2)のグラフを考える。
i!=kで、jからkへの辺があるとき、(i,j)→(j,k)の辺を貼る。
このような行列のn乗を考えればよい。


ただし初期状態として(0,0)などを用意しておく必要がある。
(0,0)へ入る辺はなくしておく。

ソースコード

int n,m,g,z;
vector<pi> e;
int f[111][111],ans[111][111],t[111][111];

void prod(int a[111][111],int b[111][111])
{
	rep(i,n)rep(j,n)
	{
		t[i][j]=0;
		rep(k,n)if(a[i][k]&&b[k][j])
		{
			t[i][j]=1; goto NEXT;
		}
		NEXT:;
	}
	rep(i,n)rep(j,n)a[i][j]=t[i][j];
}
int main()
{
	while(scanf("%d%d%d",&g,&m,&z),g)
	{
		e.clear();
		e.pb(mp(0,0));
		rep(i,m)
		{
			int a,b; scanf("%d%d",&a,&b);
			e.pb(mp(a-1,b-1)); e.pb(mp(b-1,a-1));
		}
		n=2*m+1;
		rep(i,n)rep(j,n)f[i][j]=j>0&&e[i].second==e[j].first&&e[i].first!=e[j].second;
		rep(i,n)rep(j,n)ans[i][j]=i==j;
		for(;z>0;z/=2)
		{
			if(z&1)prod(ans,f);
			prod(f,f);
		}
		rep(i,n)if(e[i].second==g-1&&ans[0][i])
		{
			puts("yes"); goto END;
		}
		puts("no"); END:;
	}
	return 0;
}