1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
   | #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <cctype> #include <cmath> #include <map> #include <queue> #define ll long long  #define ri register int  using namespace std; const int maxn=5005; const int maxm=10005; const int inf=0x7fffffff; template <class T>inline void read(T &x){     x=0;int ne=0;char c;     while(!isdigit(c=getchar()))ne=c=='-';     x=c-48;       while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;     x=ne?-x:x;     return ; } struct Edge{     int ne,to; }edge[maxm<<1]; int h[maxn],num_edge=0; inline void add_edge(int f,int to){     edge[++num_edge].ne=h[f];     edge[num_edge].to=to;     h[f]=num_edge;     return ; } int n,m; int dfn[maxn],low[maxn],tot=0; bool bridge[maxm]; void tarjan(int now,int in_edge){     int v;dfn[now]=low[now]=++tot;     for(ri i=h[now];i;i=edge[i].ne){         v=edge[i].to;         if(!dfn[v]){             tarjan(v,i);             low[now]=min(low[now],low[v]);             if(dfn[now]<low[v]){                bridge[i]=bridge[i^1]=true;                bb++;             }         }         else if(i!=(in_edge^1)){             low[now]=min(low[now],dfn[v]);         }     }     return ; } int num=0; int in_block[maxn]; bool g[maxn][maxn]; void Contraction_Point(int now){     int v;in_block[now]=num;     for(ri i=h[now];i;i=edge[i].ne){        v=edge[i].to;        if(!bridge[i]&&!in_block[v]){            Contraction_Point(v);        }     }     return ; } int du[maxn]; inline void solve(){     int ans=0,x,y;     memset(g,0,sizeof(g));     for(ri i=1;i<=n;i++){         x=in_block[i];         for(ri j=h[i];j;j=edge[j].ne){             y=in_block[edge[j].to];                 g[x][y]=g[y][x]=1;         }     }     memset(du,0,sizeof(du));     for(ri i=1;i<=num;i++){     	for(ri j=1;j<=num;j++){     		if(i!=j&&g[i][j]){du[j]++; 			} 		} 	}     for(ri i=1;i<=num;i++){         if(du[i]==1)ans++;     }     printf("%d",(int)ceil(ans/double(2)));     return ; } int main(){     int x,y;     read(n),read(m);     num_edge=1;     for(ri i=1;i<=m;i++){         read(x),read(y);         add_edge(x,y);         add_edge(y,x);     }     memset(bridge,0,sizeof(bridge));     tarjan(1,0);     memset(in_block,0,sizeof(in_block));     for(ri i=1;i<=n;i++){         if(!in_block[i]){             num++;             Contraction_Point(i);         }     }     solve();     return 0; }
 
  |