zoukankan      html  css  js  c++  java
  • LOJ10098

    USACO 2006 Jan. Gold

    为了从F个草场中的一个走到另一个,贝茜和她的同伴们不得不路过一些她们讨厌的可怕的树。奶牛们已经厌倦了被迫走某一条路,所以她们想建一些新路,使每一对草场之间都会至少有两条相互分离的路径,这样她们就有多一些选择。

    每对草场之间已经有至少一条路径,给出所有R条双向路的描述,每条路连接了两个不同的草场,请计算最少的新建道路的数量。

    路径由若干道路首尾相连而成,两条路径相互分离,是指两条路径没有一条重合的道路,但是两条分离的路径上可以有一些相同的草场。

    对于同一对草场之间,可能已经有两条不同的道路,你也可以在它们之间再建一条道路,作为另一条不同的道路。

    输入格式

    第一行输入两个整数F和R

    接下来R行,每行输入两个整数,表示两个草场,它们之间有一条道路。

    输出格式

    输出最少需要新建的道路数目。

    样例

    样例输入

    7 7
    1 2
    2 3
    3 4
    2 5
    4 5
    5 6
    5 7
    

    样例输出

    2

    数据范围与提示

    F<=5000,R<=10000

    ______________________________________________________________

    tarjan算法求双联通分量,实际上和求强联通分量是一样的,只要把双向边的反边标记为不可用就可以了。

    求出双联通分量,重新建图,统计每个分量的度,叶子节点相互连接就可以了,所以答案就是(叶子数+1)/2

    ______________________________________________________________

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=5e3+10;
     4 const int maxm=2e4+10;
     5 int n,m;
     6 struct edge
     7 {
     8     int u,v,nxt;
     9     bool pd;
    10 }e[maxm];
    11 int head[maxn],js;
    12 void addage(int u,int v)
    13 {
    14     e[++js].u=u;e[js].v=v;
    15     e[js].nxt=head[u];head[u]=js;
    16 }
    17 int low[maxn],dfn[maxn],cnt,st[maxn],top,lt[maxn],lts;
    18 void tarjan(int u)
    19 {
    20     low[u]=dfn[u]=++cnt;
    21     st[++top]=u;
    22     for(int i=head[u];i;i=e[i].nxt)
    23         if(e[i].pd==0)
    24         {
    25             e[(i&1)?i+1:i-1].pd=1;
    26             int v=e[i].v;
    27             if(!dfn[v])
    28             {
    29                 tarjan(v);
    30                 low[u]=min(low[u],low[v]);
    31             }
    32             else low[u]=min(low[u],dfn[v]);
    33             
    34         }
    35     if(low[u]==dfn[u])
    36     {
    37         lt[u]=++lts;
    38         while(st[top]!=u)lt[st[top--]]=lts;
    39         --top;
    40     }
    41 }
    42 int du[maxn];
    43 int main()
    44 {
    45     scanf("%d%d",&n,&m);
    46     for(int u,v,i=1;i<=m;++i)
    47     {
    48         scanf("%d%d",&u,&v);
    49         addage(u,v);addage(v,u);
    50     }
    51     tarjan(1);
    52     for(int u=1;u<=n;++u)
    53         for(int i=head[u];i;i=e[i].nxt)
    54         {
    55             int v=e[i].v;
    56             if(lt[u]!=lt[v])
    57             {
    58                 du[lt[u]]++;
    59                 du[lt[v]]++;
    60             }
    61         }
    62     int ans=0;
    63     for(int i=1;i<=lts;++i)
    64         if(du[i]==2)ans++;
    65     cout<<((ans+1)>>1)<<endl;
    66     return 0;
    67 }
    View Code
     
  • 相关阅读:
    Unity shader之金属质感衣服
    Unity之如何使用夜神模拟器logcat
    Unity XLua之协程
    Unity shader之ColorMask
    NGUI之实现连连看小游戏
    NGUI之使用UISprite画线
    Unity如何退出游戏
    c#之AES加密解密
    Unity shader学习之屏幕后期处理效果之高度雾,重建world pos方法2
    Unity shader学习之屏幕后期处理效果之高度雾,重建world pos方法1
  • 原文地址:https://www.cnblogs.com/gryzy/p/10985386.html
Copyright © 2011-2022 走看看