无向图和有向图其实没啥区别...
缩完点之后就变成一个树了。
我们把树中度为1的点都连起来即可。
(ans+1)/2
#include<cstdio>
#include<stack>using namespace std;
#define N 5005
struct node{
int v,next;
}e[N<<1];
int n,m,tot,head[N],low[N],dfn[N],id[N],in[N],pd,sd;
bool mark[N],mp[N][N];
stack<int>s;
void add(int x,int y){//判断是不是父边
e[++tot].v=y;
e[tot].next=head[x];
head[x]=tot;
}
bool judge(int x,int y){
if((x&1)&&y==x+1) return 1;
if(!(x&1)&&y==x-1) return 1;
return 0;
}
void tarjan(int v,int fa){
low[v]=dfn[v]=++pd;
s.push(v);
mark[v]=1;
for(int i=head[v];i;i=e[i].next){
if(judge(i,fa)) continue;
int w=e[i].v;
if(!dfn[w]){
tarjan(w,i);
low[v]=min(low[v],low[w]);
}
else if(mark[w]){
low[v]=min(low[v],dfn[w]);
}
}
int u;
if(low[v]==dfn[v]){
sd++;
do{
u=s.top();
s.pop();
id[u]=sd;
mark[u]=0;
}while(u!=v);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1,x,y;i<=m;i++){
scanf("%d%d",&x,&y);
if(!mp[x][y]){
add(x,y);add(y,x);
mp[x][y]=mp[y][x]=1;
}
}
for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,-1);
for(int i=1;i<=n;i++){
for(int j=head[i];j;j=e[j].next){
if(id[i]!=id[e[j].v]){
in[id[i]]++;
}
}
}
int ans=0;
for(int i=1;i<=sd;i++) if(in[i]==1) ans++;
printf("%d\n",(ans+1)/2);
return 0;
}