zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    org.hibernate.MappingException: duplicate import异常
    java web项目导入问题
    android.os.NetworkOnMainThreadException解决
    Eclipse无法识别小米2S手机
    ANDROID模拟器访问本地WEB应用
    【UE4】二十四、UE4内部版本引擎和官方版本引擎版本保持兼容的方法
    【UE4】二十三、UE4笔试面试题
    如何设置文件审计软件FileAudit的浏览选项
    PHP
    PHP
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3489845.html
Copyright © 2011-2022 走看看