道路建设 POJ 3352

题目链接:https://vjudge.net/problem/POJ-3352

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1005;
 7 const int maxm=1005;
 8 int n, r;
 9 struct edge {
10     int to, next;
11 } e[maxm<<1];//注意边的数量按照题目中数量输入会出现“timelimitexceeded” 错误 
12 int head[maxn], tot;
13 void add(int u, int v) {
14     e[++tot].to=v;
15     e[tot].next=head[u];
16     head[u]=tot;
17 }
18 int dfs[maxn], low[maxn], num;
19 void tarjan(int u, int fa) {//求边双连通分量
20     dfs[u]=low[u]=++num;
21     for(int i=head[u]; i; i=e[i].next) {
22         int v=e[i].to;
23         if(v==fa)continue;
24         if(!dfs[v]) {
25             tarjan(v, u);
26             low[u]=min(low[u], low[v]);
27         } else {
28             low[u]=min(low[u], dfs[v]);
29         }
30     }
31 }
32 int degree[maxn];
33 int cal() {
34     int ret=0;
35     for(int u=1; u<=n; u++)//找桥连通的各个缩点的度
36         for(int i=head[u]; i; i=e[i].next) {
37             int v=e[i].to;
38             if(low[u] != low[v])
39                 degree[low[u]]++;//注意此处细节
40         }
41     for(int i=1; i<=n; i++)
42         if(degree[i]==1)
43             ret++;
44     return ret;
45 }
46 void inif(){
47     memset(head, 0, sizeof(head));
48     memset(e, 0, sizeof(e));
49     memset(degree, 0, sizeof(degree));
50     memset(low, 0, sizeof(low));
51     memset(dfs, 0, sizeof(dfs));
52     num=tot=0;
53 }
54 int main() {
55     while(scanf("%d%d", &n, &r)!=EOF) {
56         inif();//初始化 
57         while(r--) {
58             int v, w;
59             scanf("%d%d", &v, &w);
60             add(v, w);
61             add(w, v);
62         }
63         tarjan(1, 0);
64         int leaf=cal();//计算度为1的缩点数量 ,即边双连通分量度为1的数量
65         printf("%d\n", (leaf+1)/2);
66     }
67 
68     return 0;
69 }

 

posted @ 2022-04-27 21:48  TFLSNOI  阅读(25)  评论(0编辑  收藏  举报