传送门
分析
此题要先用tarjan求点双联通分量,注意在求解是要注意一条无向边只能走一次。求完之后我们发现原来的图会变成一棵树,对于 这棵树我们发现答案是(叶子节点数量+1)/2,实际便是每两个节点之间连一条边。
代码
#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; int dfn[],low[],ist[],cnt,sum,belong[],id[],ans; vectorv[]; vectornv[]; stacka; inline void tarjan(int x,int fa){ dfn[x]=low[x]=++cnt; a.push(x); ist[x]=; int wh=; for(int i=;i<v[x].size();i++){ if(v[x][i]==fa&&!wh){ wh=; continue; } if(!dfn[v[x][i]]){ tarjan(v[x][i],x); low[x]=min(low[x],low[v[x][i]]); }else if(ist[v[x][i]]){ low[x]=min(low[x],dfn[v[x][i]]); } } if(dfn[x]==low[x]){ sum++; while(){ int u=a.top(); a.pop(); ist[u]=; belong[u]=sum; if(u==x)break; } } return; } int main(){ int n,m,i,j,k,x,y; scanf("%d%d",&n,&m); for(i=;i<=m;i++){ scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } tarjan(,); for(i=;i<=n;i++) for(j=;j<v[i].size();j++) if(belong[i]!=belong[v[i][j]]) id[belong[v[i][j]]]++; for(i=;i<=sum;i++) if(id[i]==)ans++; printf("%d\n",(ans+)/); return ; }
手机扫一扫
移动阅读更方便
你可能感兴趣的文章