rt,本来以为是求边双的板子,但是发现求完的tot跟答案不一样,tot / 2得了六十分,为什么呢QAQ
//模板来自P8436供题人题解
#include <bits/stdc++.h>
#define maxn 2000010
#define maxm 8000010
using namespace std;
int n,m,cnt = 1;
int tim;
int tot;
int dfn[maxn],low[maxn],head[maxn],belong[maxn]; //链式前向星存图
struct edge{
int nxt,to;
}a[maxm];
bool ge[maxm]; //割边判断
vector<int> G[maxn];
int outdegree[maxn];
long long ans = 0;
void add(int x,int y){ //链式前向星加边
a[++cnt].to = y;
a[cnt].nxt = head[x];
head[x] = cnt;
}
void tarjan(int x,int fa){ //fa便是来的边
dfn[x] = low[x] = ++tim;
for(int i = head[x];i;i = a[i].nxt){
int u = a[i].to;
if(!dfn[u]){
tarjan(u, i);
low[x] = min(low[x],low[u]); //更新
if(dfn[x] < low[u]){ //割边的判定方法
ge[i] = ge[i ^ 1] = true; //双向边所以都标记,i ^ 1是因为他们是相邻建的边
}
}else if(i != (fa ^ 1)){
low[x] = min(low[x],dfn[u]);
}
}
}
void dfs(int x){
belong[x] = tot;
if(x){
G[tot].push_back(x);
}
for(int i = head[x];i;i = a[i].nxt){
int u = a[i].to;
if(belong[u] || ge[i]) continue; //是割边则返回
dfs(u);
}
}
int x[maxn],y[maxn];
int main(){
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 1; i <= m; i++){
cin >> x[i] >> y[i];
// if(x == y) continue;
add(x[i],y[i]),add(y[i],x[i]);
}
for(int i = 1; i <= n; i++){
if(!dfn[i]) tarjan(i,0);
}
for(int i = 1; i <= n; i++){
if(!belong[i]) {
++tot;
dfs(i);
}
}
cout << tot / 2<< endl;
return 0;
}