公式
I - 背の順/Order of Height 解説
by
最も背が高い人が誰であるかを考えます。「他の誰かより背が低い」という情報が存在しない人のうち 1 人を自由に選んだとき、その人を最も背が高いと決めても他の情報と矛盾しません。よって、入次数が 0 の頂点を 1 つ選んでその頂点を削除する操作を繰り返すことで、与えられた情報と矛盾しない背の順の可能性が1つ得られます。
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");
}
投稿日時:
最終更新: