AOJ1055 Huge Family
問題リンク Huge Family
- 解法
ある人物からは必ず2本辺が出ています。図に起こすと、グラフは閉路がいくつか散らばっているような図になります。人物AとBの間に家族割引があったならば、clanの中でも繋がっていなければならないので、この閉路の中に登場する人物同士はclanでも繋がってなければなりません。ある1つの閉路におけるclanを考えます。この閉路は頂点N、辺の本数がN本の閉路となっています。clanの定義より、このグラフの最小全域木がclanとなります。ではその最小全域木の作り方は何通りあるかというと、コストの最も大きい辺を1本取り除くと最小全域木となるので、そのような辺の本数だけ最小全域木を作ることができます。
あとはこれを各閉路について求め、それらの積を取ってMODを取れば解けます。
- ソース
import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; //Huge Family public class AOJ1055 { int n, MOD = 10007; int[][] e, f; boolean[] v; int bfs(int s){ v[s] = true; int max = -1, c = 0; Queue<Integer> q = new LinkedList<Integer>(); q.add(s); while(!q.isEmpty()){ int p = q.poll(); for(int i=0;i<2;i++){ if(max<f[p][i]){ max = f[p][i]; c = 1; } else if(max==f[p][i])c++; if(!v[e[p][i]]){ v[e[p][i]] = true; q.add(e[p][i]); } } } return (c/2)%MOD; } void run(){ Scanner sc = new Scanner(System.in); for(;;){ n = sc.nextInt(); if(n==0)break; e = new int[n][2]; f = new int[n][2]; for(int i=0;i<n;i++)for(int j=0;j<2;j++){ e[i][j] = sc.nextInt(); f[i][j] = sc.nextInt(); } v = new boolean[n]; int res = 1; for(int i=0;i<n;i++)if(!v[i])res=(res*bfs(i))%MOD; System.out.println(res); } } public static void main(String[] args) { new AOJ1055().run(); } }