bzoj 1064 图论

我们根据能否看见建图,有向图边权设成1,然后我们转成无向图,

对于每条有向边连一条反边,边权是-1,然后从每个块中任意一个点开始

dfs,每个点有一个值,经过一条边到另一个点之后,用原来的点值和边权

更新新的点的点值,那么如果我们访问到了一个原来已经走过的点,那么我们

找到了一个环(可能是非环,就是一个点出两条有向边,然后又交在一点了),由于

数据是合法的,所以这样的非环的现在应该更新成的点值和原有的点值相等,如果不相等

的话,取差值的绝对值,就是这个环的长度。

那么我们对于所有块,每个块的环的长度都是种类数的倍数,所以取gcd就好了

还有一种情况就是没有环,全都是以链的形式存在的,对于这种形式,我们每个块

染色,然后找到每个块中点值最大的最小的差值就是最长链的长度。

无解的情况比较容易讨论,在此不再赘述。

/**************************************************************
    Problem: 1064
    User: BLADEVIL
    Language: Pascal
    Result: Accepted
    Time:284 ms
    Memory:34596 kb
****************************************************************/
 
{$M 65536000} 
//By BLADEVIL
var
    n, m                            :longint;
    pre, other, len                 :array[0..2000020] of longint;
    last                            :array[0..100010] of longint;
    l                               :longint;
    flag                            :array[0..100010] of boolean;
    size, father, key, tmin, tmax   :array[0..100010] of longint;
    g                               :array[0..2000100] of longint;
    ans1, ans2                      :longint;
   
       
procedure swap(var a,b:longint);
var
    c                               :longint;
begin
    c:=a; a:=b; b:=c;
end;
       
function min(a,b:longint):longint;
begin
    if a>b then min:=b else min:=a;
end;
   
function max(a,b:longint):longint;
begin
    if a>b then max:=a else max:=b;
end;
   
function gcd(a,b:longint):longint;
begin
    if b>a then swap(a,b);
    if b=0 then exit(a) else exit(gcd(b,a mod b));
end;
       
procedure connect(x,y,z:longint);
begin
    inc(l);
    pre[l]:=last[x];
    last[x]:=l;
    other[l]:=y;
    len[l]:=z;
end;
   
procedure dfs(x:longint);
var
    q, p                            :longint;
begin
    flag[x]:=true;
    q:=last[x];
    while q<>0 do
    begin
        p:=other[q];
        if len[q]=1 then father[p]:=x;
        if not flag[p] then
        begin
            flag[p]:=true;
            size[p]:=size[x]+len[q];
            key[p]:=key[x];
            dfs(p);
        end else
        begin
            inc(g[0]);
            g[g[0]]:=abs(size[x]+len[q]-size[p]);
            if g[g[0]]=0 then dec(g[0]);
        end;
        q:=pre[q];
    end;
end;
       
procedure init;
var
    i                               :longint;
    x, y                            :longint;
begin
    read(n,m);
    for i:=1 to m do
    begin
        read(x,y);
        connect(x,y,1);
        connect(y,x,-1);
    end;
    for i:=1 to n do father[i]:=-1;
    for i:=1 to n do if not flag[i] then dfs(i);
end;
   
procedure main;
var
    i                               :longint;
begin
    if g[0]=0 then
    begin
        fillchar(flag,sizeof(flag),false);
        for i:=1 to n do if (father[i]=-1) and (key[i]=0) then
        begin
            key[i]:=i;
            dfs(i);
        end;
        for i:=1 to n do tmax[i]:=-maxlongint;
        for i:=1 to n do tmin[i]:=maxlongint;
        for i:=1 to n do
        begin
            tmax[key[i]]:=max(tmax[key[i]],size[i]);
            tmin[key[i]]:=min(tmin[key[i]],size[i]);
        end;
        for i:=1 to n do if tmin[i]<>maxlongint then inc(ans1,tmax[i]-tmin[i]+1);
        if ans1<3 then
        begin
            writeln(-1,' ',-1);
            exit;
        end else
        begin
            writeln(ans1,' ',3);
            exit;
        end;
    end else
    begin
        ans1:=g[1];
        for i:=2 to g[0] do
            ans1:=gcd(ans1,g[i]);
        if ans1<3 then
        begin
            writeln(-1,' ',-1);
            exit;
        end else
        begin
            ans2:=0;
            for i:=3 to ans1 do
                if ans1 mod i=0 then
                begin
                    ans2:=i;
                    break;
                end;
            if ans2=0 then ans2:=ans1;
            writeln(ans1,' ',ans2);
        end;
    end;
end;
   
begin
    init;
    main;
end.

 

posted on 2013-12-24 23:17  BLADEVIL  阅读(...)  评论(... 编辑 收藏

统计