题面是图不好截QAQ
就是加点使图变成一个大的边双
先根据已有的边双缩点
会形成一棵树
贪心连叶子结点
答案=
(num+1)/2
(
n
u
m
+
1
)
/
2
#include<bits/stdc++.h>
using namespace std;
int n , m , linkk[5100] ,t;
int dfn[5100] , low[5100] , tt;
int color[5100] , tot , du[5100];
struct node{
int n , x , y;
bool flag;
}e[21000];
int read() {
bool flag=true;int num=0;char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=false;
for(;c>='0'&&c<='9';c=getchar()) num=(num<<3)+(num<<1)+c-48;
if(flag) return num; else return -num;
}
void insert(int x,int y){
e[++t].x = x;e[t].y = y;e[t].n = linkk[x];linkk[x] = t;
e[++t].y = x;e[t].x = y;e[t].n = linkk[y];linkk[y] = t;
return;
}
void trajan(int x,int fa){
dfn[x] = low[x] = ++tt;
for(int i = linkk[x];i;i = e[i].n)
if(!dfn[e[i].y]){
int y = e[i].y;
trajan( y , i );
low[x] = min( low[x] , low[y] );
if(low[y] > dfn[x]){
e[i].flag = true ,
e[i ^ 1].flag = true;
}
}
else
if( (i ^ 1) != fa)
low[x] = min( low[x] , dfn[e[i].y] );
return;
}
void dfs(int x){
color[x] = tot;
for(int i = linkk[x];i;i = e[i].n)
if(!color[e[i].y] && !e[i].flag)
dfs(e[i].y);
}
void make_node(){
t = 0;
memset(linkk,0,sizeof(linkk));
for(int i = 1;i <= m;++i){
int j = i * 2;
int x = e[j].x , y = e[j].y;
if(color[x] != color[y])
insert( color[x] , color[y] ) ,
du[color[x]]++,du[color[y]]++;
}
return;
}
int get(){
int sum = 0;
for(int i = 1;i <= tot;++i){
bool flag = true;
int k = e[linkk[i]].y;
for(int j = linkk[i];j;j = e[j].n)
if(e[j].y != k){
flag = false;
}
if(flag) sum++;
}
return sum;
}
int main(){
n = read();m = read();t = 1;
for(int i = 1;i <= m;++i){
int x = read() , y = read();
insert( x , y );
}
trajan( 1 , 0 );
for(int i = 1;i <= n;++i)
if(!color[i]) ++tot , dfs(i);
make_node();
int num = 0;
for(int i = 1;i <= tot;++i)
num += (du[i] == 1);
printf("%d",(num+1)/2);
return 0;
}