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<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<string>
 8 #include<algorithm>
 9 #include<stack>
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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值