読者です 読者をやめる 読者になる 読者になる

ヘクトのメモ

なんとなくいろいろ書いていくと思います.

AOJ 2608 Minus One

これは比較的解きやすいと思う.
最後の最後に気を付けることあるけど.

問題文
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2608


解法
頂点sとtからbfsを用いて,sとtからの全ての点への最短距離を求める.
iからjへの最短距離をdist(i,j)とおくと
求めるものはdist(s,i)+1+dist(j,t)=dist(s,t)を満たす(i,j)の組である.
sとtからの最短距離がiである頂点数を前計算すれば,簡単に求められる.

計算量は,bfsの部分でO(N),組み合わせの計算でO(N),よってO(N)

ソースコードは以下の通り

const int vmax=100010;
int sdist[vmax];
int tdist[vmax];

ll snum[vmax];
ll tnum[vmax];

vi graph[vmax];

int main(void){
	int n,m,s,t;
	cin  >> n >> m >> s >> t;
	s--,t--;

	rep(i,m){
		int x,y;
		cin >> x >> y;
		x--,y--;
		graph[x].pb(y);
		graph[y].pb(x);
	}
	rep(i,vmax) sdist[i]=tdist[i]=-1;

	queue<pii> q;
	sdist[s]=0; q.push(mp(s,0));
	while(!q.empty()){
		pii cur=q.front();q.pop();
		int v=cur.first;
		int c=cur.second;
		for(auto &v2:graph[v]){
			if(sdist[v2]==-1){
				sdist[v2]=c+1;
				q.push(mp(v2,c+1));
			}
		}
	}

	tdist[t]=0; q.push(mp(t,0));
	while(!q.empty()){
		pii cur=q.front();q.pop();
		int v=cur.first;
		int c=cur.second;
		for(auto &v2:graph[v]){
			if(tdist[v2]==-1){
				tdist[v2]=c+1;
				q.push(mp(v2,c+1));
			}
		}
	}
	rep(i,n) snum[sdist[i]]++;
	rep(i,n) tnum[tdist[i]]++;
	int sp=sdist[t];
	ll ans=0LL;
	rep(i,sp-1) ans+=snum[i]*tnum[sp-2-i];
	cout << ans << endl;
	return 0;
}