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

 

 

posted on 2019-06-06 15:49  gryzy  阅读(213)  评论(0编辑  收藏  举报

导航