poj3177弱化版
双连通分量缩点,答案为(叶子节点+1)/2
(还不带重边,实在没什么好说的了)
#include<bits/stdc++.h>
#define LEN 1000006
using namespace std;
inline int getint(){
int x=0,p=1;
char c=getchar();
while(!isdigit(c)){
if(c=='-')p=-1;
c=getchar();
}
while(isdigit(c)){
x=(x<<3)+(x<<1)+(c^'0');
c=getchar();
}
return x*p;
}
int n,m;
struct road{
int e,nxt;
}r[LEN],r2[LEN];
int tot=1,first[LEN],dfn[LEN],low[LEN],dfst=0;
int stk[LEN],top=0;
bool ins[LEN];
inline void creat(int a,int b){
r[++tot].e=b;
r[tot].nxt=first[a];
first[a]=tot;
}
int bp=0,belong[LEN];
void dfs1(int cur,int inr){
dfn[cur]=low[cur]=++dfst;
stk[++top]=cur;
ins[cur]=1;
for(int i=first[cur];i;i=r[i].nxt){
int v=r[i].e;
if(i==(inr^1))continue;
if(!dfn[v]){
dfs1(v,i);
low[cur]=min(low[cur],low[v]);
}
else{
low[cur]=min(low[cur],dfn[v]);
}
}
//cout<<cur<<" "<<dfn[cur]<<" "<<low[cur]<<endl;
if(dfn[cur]==low[cur]){
++bp;
int j;
do{
j=stk[top--];
belong[j]=bp;
ins[j]=0;
}while(j!=cur);
}
}
int tot2=1,f2[LEN];
inline void creat2(int a,int b){
r2[++tot2].e=b;
r2[tot2].nxt=f2[a];
f2[a]=tot2;
}
int leaves=0;
bool vis[LEN];
void dfs2(int cur,int fa){
vis[cur]=1;
int son=0;
for(int i=f2[cur];i;i=r2[i].nxt){
int v=r2[i].e;
if(v==fa)continue;
if(vis[v])continue;
++son;
dfs2(v,cur);
}
if(son==1&&cur==fa){
++leaves;
}
else{
if(son==0){
++leaves;
}
}
}
int main(){
n=getint(),m=getint();
for(int i=1;i<=m;++i){
int a=getint(),b=getint();
creat(a,b);
creat(b,a);
}
dfs1(1,-5);
if(bp==1){
cout<<0;
return 0;
}
for(int i=1;i<=n;++i){
for(int j=first[i];j;j=r[j].nxt){
int v=r[j].e;
if(belong[i]!=belong[v]){
creat2(belong[i],belong[v]);
creat2(belong[v],belong[i]);
}
}
}
dfs2(1,1);
//cout<<leaves<<endl;
cout<<(leaves+1)/2;
return 0;
}