公式

I - 背の順/Order of Height 解説 by kyopro_friends


\(1\) から \(N\) の番号がついた \(N\) 個の頂点を持ち、「人 \(A_i\) は人 \(B_i\) より背が高い」という情報が存在するとき、\(A_i\) から \(B_i\) への有向辺をもつグラフを考えます。

このグラフにおいて、サイクルが存在しないことが、答えがYesであるための必要十分条件です。

証明 サイクルが存在するとき答えがNoになることは明らかです。サイクルが存在しないとき、情報と矛盾しない背の順の1つを次の手順により具体的に構築できます。
最も背が高い人が誰であるかを考えます。「他の誰かより背が低い」という情報が存在しない人のうち 1 人を自由に選んだとき、その人を最も背が高いと決めても他の情報と矛盾しません。よって、入次数が 0 の頂点を 1 つ選んでその頂点を削除する操作を繰り返すことで、与えられた情報と矛盾しない背の順の可能性が1つ得られます。

グラフにサイクルが存在するかどうかの判定は「入次数が 0 の頂点を順に削除し、全ての頂点を削除できるか」によりできるため、適切な実装で \(O(N^2)\) または \(O(N+M)\) でこの問題を解くことができます。

実装例(C) \(O(N^2)\)

#include<stdio.h>

int e[110][110];
int deg[110];
int checked[110];

int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		a--,b--;
		e[a][b]++;
		deg[b]++;
	}
	
	for(int _=0;_<n;_++){
		int v=-1;
		for(int i=0;i<n;i++)if(!checked[i]&&!deg[i])v=i;
		if(v==-1){
			puts("No");
			return 0;
		}
		checked[v]=1;
		for(int i=0;i<n;i++)deg[i]-=e[v][i];
	}
	
	puts("Yes");
}

投稿日時:
最終更新: