分离的路径
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 #include3 #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 }