[BZOZ1064][NOI2008]假面舞会 图论

来源:互联网 发布:yum环境搭建 编辑:程序博客网 时间:2024/04/27 21:59

看来从简单入手到复杂情况的思想还没有形成。。。
这题就需要分情况讨论的,显然每个弱联通块是可以单独拿出来讨论的。
一棵树?最大为树深,最小为3(如果树有那么深的话)
一个环?最大为环上点数,最小为环上点数的最小约数(>=3)
一个弱联通意义下的环?我们可以发现一个性质,如果一个点所练的两条边方向相反,那么这两条边是可以抵消掉的,就变成原来的环啦。
于是我们就有思路了,把有向图转化为无向图,正向边权为1,反向边权为-1。树深就对应着最长链长:最大深度-最小深度(为非正数)+1,环长也可以搞了,一遍bfs两个都搞定。
最后统计答案,若没有环,那么最大为树深之和,最小为3;若有环,树都无效了,最大为所有环长的gcd,最小为gcd的最小约数(>=3).
两个环有公共部分是不影响答案的。
代码:

type  edge=^edgenode;  edgenode=record    t,w:longint;    next:edge;  end;var  n,m,i,x,y,gcd,sum,d:longint;  con:array[0..100100]of edge;  visit:array[0..100100]of boolean;  dl,dist:array[0..100100]of longint;procedure ins(x,y,w:longint);var  p:edge;begin  new(p);  p^.t:=y;  p^.w:=w;  p^.next:=con[x];  con[x]:=p;end;function min(x,y:longint):longint;begin  if x>y then exit(y)  else exit(x);end;function max(x,y:longint):longint;begin  if x<y then exit(y)  else exit(x);end;function qgcd(x,y:longint):longint;begin  if y=0 then exit(x)  else exit(qgcd(y,x mod y));end;function bfs(v:longint):longint;var  maxdist,mindist,head,tail,x:longint;  p:edge;begin  head:=1;  tail:=1;  dl[1]:=v;  visit[v]:=true;  dist[v]:=0;  maxdist:=0;  mindist:=0;  while head<=tail do  begin    x:=dl[head];    p:=con[x];    while p<>nil do    begin      if visit[p^.t] then gcd:=qgcd(dist[x]-dist[p^.t]+p^.w,gcd)      else      begin        visit[p^.t]:=true;        inc(tail);        dl[tail]:=p^.t;        dist[p^.t]:=dist[x]+p^.w;        maxdist:=max(maxdist,dist[p^.t]);        mindist:=min(mindist,dist[p^.t]);      end;      p:=p^.next;    end;    inc(head);  end;  exit(maxdist-mindist+1);end;begin  readln(n,m);  for i:=1 to m do  begin    readln(x,y);    ins(x,y,1);    ins(y,x,-1);  end;  gcd:=0;  fillchar(visit,sizeof(visit),0);  for i:=1 to n do    if not visit[i] then inc(sum,bfs(i));  gcd:=abs(gcd);  if gcd>0 then  begin    if gcd<3 then writeln(-1,' ',-1)    else    begin      for i:=3 to gcd do        if gcd mod i=0 then break;      writeln(gcd,' ',i);    end;  end  else  begin    if sum<3 then writeln(-1,' ',-1)    else writeln(sum,' ',3);  end;end.
0 0
原创粉丝点击