对于同一对草场之间,可能已经有两条不同的道路
题真的应该看仔细啊
//一个问题,如何变成 边双联通分量 //leaf+1>>1 #include<cstdio> #include<cstdlib> #include<stack> using namespace std; inline int read() { int x=0;char c=getchar(); while(c<'0' || c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar(); return x; } int n,m; const int N=5003,M=10003; int col[N],sum; int tot=1,head[N]; int ev[M<<1],enx[M<<1]; void add(int u,int v) { ev[++tot]=v,enx[tot]=head[u],head[u]=tot; ev[++tot]=u,enx[tot]=head[v],head[v]=tot; } int dfn[N],low[N],cnt; stack <int> s; void tarjan(int rt,int pre)//强连通缩点 { dfn[rt]=low[rt]=++cnt; s.push(rt); for(int i=head[rt];i;i=enx[i]) if((pre^1) != i )//对于同一对草场之间,可能已经有两条不同的道路 { if(!dfn[ev[i]]) tarjan(ev[i],i); low[rt]=min(low[rt],low[ev[i]]); } if(dfn[rt]==low[rt]) { col[rt]=++sum; while(s.top() !=rt) col[s.top() ]=sum,s.pop() ; s.pop() ; } } int in[N]; int main() { n=read(),m=read(); for(int i=1;i<=m;i++) add(read(),read()); for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0); int ans=0; for(int i=2;i<tot;i+=2) if(col[ev[i]]!=col[ev[i|1]] ) in[col[ev[i]]]++,in[col[ev[i|1]]]++; for(int i=1;i<=sum;i++) if(in[i]==1) ans++; printf("%d\n",ans+1>>1); return 0; }