Vijos 桐桐的糖果计划 (tarjan求桥+双连通分量)

背景

桐桐是一个快乐的小朋友,他生活中有许多许多好玩的事,让我们一起来看看吧……

描述

桐桐很喜欢吃棒棒糖。他家处在一大堆糖果店的附近。

但是,他们家的区域经常出现塞车、塞人等情况,这导致他不得不等到塞的车或人走光了他才能去买到他最爱吃的棒棒糖品种。于是,他去找市长帮他修路,使得每两个糖果店之间至少有两条完全不同的路。可是市长经费有限,于是让桐桐找出哪些路被塞住后会使某些糖果店与糖果店间无法到达及最少的修路条数。你能帮助他吃到他最喜爱的糖果吗?
注:
1->3->2 和 1->3->4->2 为不完全不同的路,即不符合题意的路。

1->3->4->2 和 1->5->2 为完全不同的路,即符合题意的路。

格式

输入格式

输入第一行是两个数n,m(n<=5000,m<=10000)
接下来的m行,每行两个数i,j,表示i,j间有一条边连接。

输出格式

输出有两行。第一行为塞住后就不可以到达某些糖果店的道路条数,第二行为最少的修路条数。

样例1

样例输入1

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

样例输出1

3
2

限制

提示


1 2 3
+---+---+ 
| |
| |
6 +---+---+ 4
/ 5


7 +

上图是样例所表示的一个图。

下图是改变后的图,其中虚线表示应连接的边。


1 2 3
+---+---+
: | |
: | |
6 +---+---+ 4
/ 5 :
/ :
/ :
7 + - - - -

 

 1 /* 
 2     tarjan求桥+双连通分量
 3     注意判重边
 4 */
 5 #include<cstdio>
 6 #include<cstring>
 7 #include<iostream>
 8 #define MAXN 5010
 9 
10 using namespace std;
11 
12 int n,m;
13 
14 struct node {
15     int to;
16     int next;
17 };
18 node e[MAXN*2];
19 int head[MAXN],tot;
20 
21 int dfn[MAXN],low[MAXN],stack[MAXN],belong[MAXN],top,idex,cnt,ans;
22 bool vis[MAXN];
23 
24 int in[MAXN];
25 
26 inline void read(int&x) {
27     int f=1;x=0;char c=getchar();
28     while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
29     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();}
30     x=x*f;
31 }
32 
33 inline void add(int x,int y) {
34     e[tot].to=y;
35     e[tot].next=head[x];
36     head[x]=tot++;
37 }
38 
39 inline void tarjan(int u,int fa) {
40     dfn[u]=low[u]=++idex;
41     stack[++top]=u;
42     vis[u]=true;
43     for(int i=head[u];i!=-1;i=e[i].next) {
44         if(i==(fa^1)) continue;//判重边
45         int v=e[i].to;
46         if(!dfn[v]) {
47             tarjan(v,i);
48             low[u]=min(low[u],low[v]);
49             if(low[v]>dfn[u]) ans++;//求桥的数量
50         }
51         else if(vis[u]) low[u]=min(dfn[v],low[u]);
52     }
53     if(dfn[u]==low[u]) {
54         cnt++;
55         int t;
56         do {
57             t=stack[top--];
58             belong[t]=cnt;
59             vis[t]=false;
60         }while(u!=t);
61     }
62     return;
63 }
64 
65 int main() {
66     int x,y;
67     read(n);read(m);
68     memset(head,-1,sizeof head);
69     for(int i=1;i<=m;i++) {
70         read(x);read(y);
71         add(x,y);add(y,x);
72     }
73     for(int i=1;i<=n;i++)
74       if(!dfn[i])
75         tarjan(i,-1);
76     printf("%d\n",ans);
77     for(int i=1;i<=n;i++)
78       for(int j=head[i];j!=-1;j=e[j].next) {
79             int v=e[j].to;
80           if(belong[i]!=belong[v])
81             in[belong[i]]++;
82       }
83     ans=0;
84     for(int i=1;i<=n;i++)
85       if(in[i]==1)
86         ans++;
87     printf("%d\n",(ans+1)/2);
88     return 0;
89 }
代码

 

posted @ 2017-06-08 10:00  拿叉插猹哈  阅读(105)  评论(0编辑  收藏  举报