道路建设 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 }