zoukankan      html  css  js  c++  java
  • [POJ1144][BZOJ2730]tarjan求割点

    求割点

    一种显然的n^2做法:

      枚举每个点,去掉该点连出的边,然后判断整个图是否联通

    用tarjan求割点:

      分情况讨论

      如果是root的话,其为割点当且仅当下方有两棵及以上的子树

      其他情况

      设当前节点为u,一个儿子节点为v

      存在low[v]>=dfn[u],也就是说其儿子节点v能连到的最前面的点都在u的下面

      也就是当u断开的时候,u之前的点与以v为根的子树必然分成两个独立的块

      那么这个时候u就是割点


      

    Network

    A Telephone Line Company (TLC) is establishing a new telephone cable network. They are connecting several places numbered by integers from 1 to N . No two places have the same number. The lines are bidirectional and always connect together two places and in each place the lines end in a telephone exchange. There is one telephone exchange in each place. From each place it is 
    possible to reach through lines every other place, however it need not be a direct connection, it can go through several exchanges. From time to time the power supply fails at a place and then the exchange does not operate. The officials from TLC realized that in such a case it can happen that besides the fact that the place with the failure is unreachable, this can also cause that some other places cannot connect to each other. In such a case we will say the place (where the failure 
    occured) is critical. Now the officials are trying to write a program for finding the number of all such critical places. Help them.

      直接贴模板

    program poj1144;
    const maxn = 10010;
    var n,e,i,j,x,y,time,ans,u,v:longint;
        fa,next,link,low,dfn,hash:array[-1..maxn]of longint;
        vis:array[-1..maxn]of boolean;
    
    procedure add(x,y:longint);
    begin
        inc(e);fa[e]:=y;next[e]:=link[x];link[x]:=e;
        inc(e);fa[e]:=x;next[e]:=link[y];link[y]:=e;
    end;
    
    function min(a,b:longint):longint;
    begin
        if a<b then exit(a) else exit(b);
    end;
    
    procedure tarjan(p:longint);
    var j:longint;
    begin
        inc(time);dfn[p]:=time;low[p]:=time;vis[p]:=false;
        j:=link[p];
        while j<>0 do
        begin
            if vis[fa[j]] then
            begin
                tarjan(fa[j]);
                if low[fa[j]]>=dfn[p] then inc(hash[p]);
                low[p]:=min(low[p],low[fa[j]]);
            end else low[p]:=min(low[p],dfn[fa[j]]);
            j:=next[j];
        end;
    end;
    
    begin
        //assign(input,'poj1144.in');reset(input);
        readln(n);
        while n<>0 do
        begin
            fillchar(link,sizeof(link),0);
                    fillchar(hash,sizeof(hash),0);
            fillchar(next,sizeof(next),0);
            e:=0;
            read(u);
                    while u<>0 do
                    begin
                            while not eoln do
                            begin
                                    read(v);
                                    add(u,v);
                            end;
                            readln;read(u);
                    end;
                    readln;
            fillchar(vis,sizeof(vis),true);time:=0;
            for i:=1 to n do if vis[i] then tarjan(i);
            ans:=0;
            if hash[1]>1 then inc(ans);
            for i:=2 to n do if hash[i]>0 then inc(ans);
            writeln(ans);
                    readln(n);
        end;
    
    end.

    矿场搭建

    煤矿工地可以看成是由隧道连接挖煤点组成的无向图。为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处。于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖煤点的工人都有一条道路通向救援出口。请写一个程序,用来计算至少需要设置几个救援出口,以及不同最少救援出口的设置方案总数。

      首先对答案有影响的显然只有割点

      然后考虑把所有割点都去掉,剩下的联通块中如果只与一个割点相连

      这个块中就要放一个出口

      最后特判整个图是一个联通块的情况

      

    program bzoj2730;
    const maxn = 101000;maxm = 101000;
    var n,e,time,x,y,ans1,ans2,test,root,tot,m,col:int64;
        i,j:longint;
        fa,next,stack:array[-1..maxm]of int64;
        vis,cut,used,exi:array[-1..maxn]of boolean;
        link,dfn,low,hash,opt:array[-1..maxn]of int64;
     
    function min(a,b:int64):int64;
    begin
        if a<b then exit(a) else exit(b);
    end;
     
    procedure add(x,y:int64);
    begin
        inc(e);fa[e]:=y;next[e]:=link[x];link[x]:=e;
        inc(e);fa[e]:=x;next[e]:=link[y];link[y]:=e;
    end;
     
    procedure tarjan(p:int64);
    var j:int64;
    begin
        inc(time);dfn[p]:=time;low[p]:=time;vis[p]:=false;stack[time]:=p;
        j:=link[p];
        while j<>0 do
        begin
            if vis[fa[j]] then
            begin
                tarjan(fa[j]);
                if low[fa[j]]>=dfn[p] then inc(hash[p]);
                low[p]:=min(low[p],low[fa[j]]);
            end else low[p]:=min(low[p],dfn[fa[j]]);
            j:=next[j];
        end;
    end;
     
    function bfs(s:int64):int64;
    var head,tail,x,j:int64;
    begin
        fillchar(used,sizeof(used),true);
        tot:=0;head:=0;tail:=1;opt[1]:=s;vis[s]:=false;
        while head<>tail do
        begin
            inc(head);x:=opt[head];j:=link[x];
            while j<>0 do
            begin
                if (vis[fa[j]])and(not cut[fa[j]]) then
                begin
                    vis[fa[j]]:=false;
                    inc(tail);opt[tail]:=fa[j];
                end else
                if (cut[fa[j]])and(used[fa[j]]) then
                begin
                    inc(tot);
                    used[fa[j]]:=false;
                end;
                j:=next[j];
            end;
        end;
        exit(tail);
    end;
     
    begin
        //assign(input,'bzoj2730.in');reset(input);
           // assign(output,'col.out');rewrite(output);
        readln(m);
            test:=0;
        while m<>0 do
        begin
                    inc(test);
            fillchar(next,sizeof(next),0);
            fillchar(link,sizeof(link),0);
                    fillchar(exi,sizeof(exi),false);
            e:=0;time:=0;n:=0;
            for i:=1 to m do
            begin
                readln(x,y);
                            if x>n then n:=x;
                            if y>n then n:=y;
                            exi[x]:=true;exi[y]:=true;
                add(x,y);
            end;
            fillchar(vis,sizeof(vis),true);
            fillchar(hash,sizeof(hash),0);
                    fillchar(cut,sizeof(cut),false);
            for i:=1 to n do if (vis[i])and(exi[i]) then
                    begin
                            tarjan(i);
                            dec(hash[i]);
                    end;
                    for i:=1 to n do if hash[i]>0 then cut[i]:=true;
            ans1:=0;ans2:=1;col:=0;
            fillchar(vis,sizeof(vis),true);
            for i:=1 to n do if (not cut[i])and(vis[i])and(exi[i]) then
            begin
                tot:=0;x:=bfs(i);inc(col);
                if tot = 1 then
                begin
                    inc(ans1);
                    ans2:=ans2*x;
                end;
            end;
            if col = 1 then writeln('Case ',test,': ',2,' ',n*(n-1) >> 1)
            else writeln('Case ',test,': ',ans1,' ',ans2);
            readln(m);
        end;
    end.
  • 相关阅读:
    Java基础知识强化之IO流笔记39:字符流缓冲流之复制文本文件案例01
    阿里云服务器绕过25端口发邮件
    springboot在lunix后台启动,退出账号也不关闭
    创建Maven项目出错 pom出错
    corn表达式 经典
    开发微信公众号基本配置参数错误
    Spring与ActiveMQ整合
    log4j.properties 打印到控制台 写法
    如何在spring环境中做单元测试
    添加jar包到本地Maven仓库
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4459959.html
Copyright © 2011-2022 走看看