jzoj1499 街道

11 篇文章 0 订阅
6 篇文章 0 订阅

Description

在城市里很容易迷路,有的街道一会儿平行一会儿又相交。现在市长为了维护城市形象,他表示:“我们的街道要么平行,要么垂直相交,不存在其他关系”。
你作为观察员准备去当地实地考察,得到一些街道之间的关系,这些关系只能是平行和垂直相交两种。
输入这些街道的关系,同时提出一些新的问题,你来帮忙回答。

Input

输入第一行包含两个整数M和N(1<=M,N<=100000),接下来M行每行包含一个考察结果,每个考察结果包含三个用若干个空格隔开的单词组成:两个街道的名字和“parallel”或“intersect”表示这两条街道之间的关系,每个街道的名字由不超过100个大写或小写字母组成。
接下来N行描述N次询问,每行输入两个由若干个空格隔开的街道名。

Output

如果考察结果与市长的话有矛盾,则输出“Waterloo”,否则输出N行,第i行对应第i次询问的结果,有“parallel”、“intersect”和“unknown”三种情况,分别表示“平行”、“垂直相交”以及“不知道”

Sample Input

3 3
fourthstreet fifthstreet parallel
fifthstreet sixthstreet parallel
fourthavenue fifthstreet intersect
sixthstreet fourthstreet
sixthstreet fourthavenue
sixthstreet King

Sample Output

parallel
intersect
unknown

Sample Input2:

2 1
King Weber parallel
King Weber intersect
King Weber

Sample Output2:

Waterloo

【数据说明】

20%的数据 1<=M,N<=100;
100%的数据 1<=M,N<=100000

算法讨论

如果两条线要平行,要么(1)题目直接给出关系 (2)平行与同一条平行的线 (3)垂直与同一条线,首先用哈希给每条街道编码,当x与y平行时,将x和y、x+mo和y+mo分别放入同一集合,垂直时,x和y+mo、x+mo和y,这样当满足第3个要求是x和y将同一集合。
const
  mo=245507;
var
  f:array[0..mo*2] of longint;
  ha:array[0..mo] of string;
function find(x:longint):longint;
begin
  if f[x]=x then exit(x);
  f[x]:=find(f[x]);
  exit(f[x]);
end;
procedure lian(x,y:longint);
var
  xx,yy:longint;
begin
  xx:=find(x);
  yy:=find(y);
  if xx<>yy then f[xx]:=yy;
end;
function hh(x:string):longint;
var
  i:longint;
begin
  hh:=0;i:=1;
  while i<=length(x) do
    begin
      hh:=(hh*53*i+ord(x[i])*i*59) mod mo;
      inc(i);
    end;
  while (ha[hh]<>'')and(ha[hh]<>x) do
    hh:=(hh+1) mod mo;
end;
var
  n,m,i,x,y:longint;
  xx,yy,s:string;
begin
  readln(m,n);
  for i:=0 to mo*2 do
    f[i]:=i;
  for i:=1 to m do
    begin
      readln(s);
      xx:=copy(s,1,pos(' ',s)-1);
      x:=hh(xx);
      if ha[x]='' then ha[x]:=xx;
      delete(s,1,pos(' ',s));
      yy:=copy(s,1,pos(' ',s)-1);
      y:=hh(yy);
      if ha[y]='' then ha[y]:=yy;
      delete(s,1,pos(' ',s));
      if s='parallel' then
        begin
          lian(x,y);
          lian(x+mo,y+mo);
          if (find(x)=find(y+mo))or(find(y)=find(x+mo)) then
            begin
              writeln('Waterloo');
              exit;
            end;
        end
      else
        begin
          lian(x,y+mo);
          lian(x+mo,y);
          if find(x)=find(y) then
            begin
              writeln('Waterloo');
              exit;
            end;
        end;
    end;
  for i:=1 to n do
    begin
      readln(s);
      xx:=copy(s,1,pos(' ',s)-1);
      x:=hh(xx);
      delete(s,1,pos(' ',s));
      y:=hh(s);
      if (ha[x]='')or(ha[y]='')or(ha[x]<>xx)or(ha[y]<>s) then
        begin
          writeln('unknown');
          continue;
        end
      else
        if (find(x)=find(y))or(find(x+mo)=find(y+mo)) then
        writeln('parallel')
      else
        if (find(x)=find(y+mo))or(find(x+mo)=find(y)) then
          writeln('intersect')
      else writeln('unknown');
    end;
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值