BZOJ1718 分离的路径 【例题精讲】

分离路径

Description

为了从F(1≤F≤5000)个草场中的一个走到另一个,贝茜和她的同伴们有时不得不路过一些她们讨厌的可怕的树.奶牛们已经厌倦了被迫走某一条路,所以她们想建一些新路,使每一对草场之间都会至少有两条相互分离的路径,这样她们就有多一些选择。每对草场之间已经有至少一条路径.给出所有R(F-1≤R≤10000)条双向路的描述,每条路连接了两个不同的草场,请计算最少的新建道路的数量, 路径由若干道路首尾相连而成.两条路径相互分离,是指两条路径没有一条重合的道路.但是,两条分离的路径上可以有一些相同的草场. 对于同一对草场之间,可能已经有两条不同的道路,你也可以在它们之间再建一条道路,作为另一条不同的道路。

Input

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

Output

最少的需要新建的道路数。

Sample Input 1

7 7

1 2

2 3

3 4

2 5

4 5

5 6

5 7

Sample Output 1

2

 
这道题在图论里比较深,属于tarjan的内容,而且是无向图部分的tarjan。
通过题目我们就大概知道,是要让最后的图变成一个双连通图,最少需要加多少边,学过tarjan的同学会想得到,我们首先把所有的双联通分量都缩成点,然后会得到一棵树,之后我们只需要把每个叶子结点都连起来即可!
而需要的边数是多少呢?
(叶子结点+1)/2;
为什么呢,各位同学可以自己证明一下哦;
 
下面上代码!
 
 1 //唇齿间缱倦到声沙; 
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 #include<string>
 8 #include
 9 #include
10 #define ms(a) memset(a,0,sizeof(a))
11 using namespace std;
12 const int MAXN=1010;
13 const int MAXM=1000010;
14 int head[MAXN],next[MAXM],ver[MAXM],indexx=0;
15 int dfn[MAXN],low[MAXN],belong[MAXN],cnt=0;
16 int indegree[MAXN],xxx[MAXM];
17 int father[MAXN],sign[MAXN];
18 bool vis[MAXN]={0};
19 int tot=0; 
20 int k=0;
21 int counts=0;
22 int n,m;
23 stack<int>s;
24 inline void add(int x,int y)
25 {
26     ver[indexx]=y;
27     xxx[indexx]=x;
28     next[indexx]=head[x];
29     head[x]=indexx;
30     sign[indexx]=counts;
31 }
32 void tarjan(int x)
33 {
34     dfn[x]=low[x]=++tot;
35     s.push(x);
36     vis[x]=true;
37     for(int i=head[x];i;i=next[i]){
38         int y=ver[i];
39         if(sign[i]==father[x]) continue;
40             if(dfn[y]==0){
41                 father[y]=sign[i];
42                 tarjan(y);
43                 low[x]=min(low[x],low[y]);
44             }
45             else if(vis[y]&&low[x]>dfn[y]){ 
46                 low[x]=dfn[y];
47             }
48         
49     }
50     if(dfn[x]==low[x]){
51         cnt++;
52         while(1){
53             int xx=s.top();
54             belong[xx]=cnt;
55             vis[xx]=false;
56             s.pop();
57             if(xx==x)break;
58         }
59         vis[x]=false;
60         belong[x]=cnt;
61     }
62     return ;
63 }
64 int main()
65 {
66     //freopen("3.in","r",stdin);
67     //freopen("3.out","w",stdout);
68     scanf("%d%d",&n,&m);
69     for(int i=1;i<=m;i++){
70         int x,y;
71         scanf("%d%d",&x,&y);
72         counts++;indexx++;add(x,y);indexx++;add(y,x);
73         father[x]=y;father[y]=x;
74     }
75     memset(vis,false,sizeof(vis));
76     for(int i=1;i<=n;i++){
77         if(!belong[i]) tarjan(i);
78     }
79     ms(indegree);
80     for(int i=1;i<=indexx;i=i+2){
81         int x=belong[xxx[i]];
82         int y=belong[ver[i]];
83         if(x==y)continue;
84         indegree[x]++;
85         indegree[y]++;
86     }int k=0;
87     for(int i=1;i<=cnt;i++){
88         if(indegree[i]==1)k++;
89     }
90     printf("%d",(k+1)/2);
91     puts("");
92     //fclose(stdin);
93     //fclose(stdout);
94     return 0;
95 }
View Code

 

 

转载于:https://www.cnblogs.com/Alan-Luo/articles/8723265.html

你可能感兴趣的:(BZOJ1718 分离的路径 【例题精讲】)