AOJ1134 Name the Crossing
問題リンク Name the Crossing
- 解法
「通りの名前」を頂点にしたグラフを作って解いていきます。
まず、XとYが違う方向の通りかを判定するためのグラフを作ります。これは色塗り問題と考えることができます。同じ色で塗られていたらそれは同じ方向です。ただし、YESと答えるためには、2つの通りの方向の違いが曖昧だとダメです。なので、違う連結成分に含まれているならばそれらはNOとなります。これは、違う連結成分に使う色を変えることで対処できます。
次は、水準の上下関係を表す有向グラフを作ります。B→Aという辺で、Aの水準がB以上であることを表します。A→B、B→Aの辺が張られていたら、AとBが同水準であることを表します。
入力のN個の情報から、そのままこの辺がN本引けます。
次にXとYの通りが同水準であるかどうかを全て判定します。通りの名前は高々200種類なので間に合います。
これでグラフは完成です。クエリで"X-Y"という入力が来たら、「XとYの色が確実に異なる」且つ「グラフ上でYの頂点からXの頂点へ行くことができる」が成り立つかを調べればいいです。
- ソース
import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Scanner; import java.util.Set; //Name the Crossing public class AOJ1134 { class R{ int id, col; Set<Integer> adj, eq; boolean visit; public R(int id) { this.id = id; col = -1; eq = new HashSet<Integer>(); adj = new HashSet<Integer>(); } void color(int c){ if(visit)return; col = c; visit = true; for(int v:adj)rs[v].color(c%2==0?(c+1):(c-1)); } boolean reach(int g){ if(id==g)return true; if(visit)return false; visit = true; for(int v:eq)if(rs[v].reach(g))return true; return false; } } int ID; Map<String, R> ref; Set<String> streets; String[] names; R get(String s){ if(ref.containsKey(s))return ref.get(s); R res = new R(ID); names[ID] = s; rs[ID++] = res; ref.put(s, res); return res; } R[] rs; void reset(){ for(int i=0;i<ID;i++)rs[i].visit = false; } void run(){ Scanner sc = new Scanner(System.in); for(;;){ int n = sc.nextInt(); if(n==0)break; ID = 0; ref = new HashMap<String, R>(); rs = new R[200]; names = new String[200]; streets = new HashSet<String>(); while(n--!=0){ String t = sc.next(); streets.add(t); String s[] = t.split("-"); R a = get(s[0]), b = get(s[1]); a.adj.add(b.id); b.adj.add(a.id); b.eq.add(a.id); } int col = 0; for(int i=0;i<ID;i++){ if(rs[i].visit)continue; rs[i].color(col); col+=2; } int N = ID; for(int i=0;i<N;i++)for(int j=i+1;j<N;j++){ boolean C, D, E; C = false; D = E = true; for(int k=0;k<N;k++){ if(k==i||k==j)continue; if(rs[i].adj.contains(k)&&rs[j].adj.contains(k))C = true; if(streets.contains(names[k]+"-"+names[i])&&streets.contains(names[j]+"-"+names[k]))D = false; if(streets.contains(names[i]+"-"+names[k])&&streets.contains(names[k]+"-"+names[j]))E = false; if(!D||!E)break; } if(C&&D&&E){ R a = get(names[i]), b = get(names[j]); a.eq.add(b.id); b.eq.add(a.id); } } System.out.println(N); int m = sc.nextInt(); while(m--!=0){ String[] t = sc.next().split("-"); R a = get(t[0]), b = get(t[1]); if(a.col==b.col||Math.abs(a.col-b.col)>=2||a.col==-1||b.col==-1){ System.out.println("NO"); continue; } reset(); System.out.println(b.reach(a.id)?"YES":"NO"); } } } public static void main(String[] args) { new AOJ1134().run(); } }