1. 程式人生 > >Newcoder contest 392 I 逛公園 (無向圖割邊模板)

Newcoder contest 392 I 逛公園 (無向圖割邊模板)

參觀 mes include 無法 mil 重復 get color bit

<題目鏈接>

題目描述:

月月和華華一起去逛公園了。公園很大,為了方便,可以抽象的看成一個N個點M條邊的無向連通圖(點是景點,邊是道路)。公園唯一的入口在1號點,月月和華華要從這裏出發,並打算參觀所有的景點。因為他們感情很好,走多遠都不會覺得無聊,所以所有景點和道路都可以無數次的重復經過。月月發現,有些路可走可不走,有些路則必須要走,否則就無法參觀所有的景點。現在月月想知道,有幾條路是不一定要經過的。因為這是個很正常的公園,所以沒有重邊和自環。$(1 \leq N\leq10^5,1 \leq M\leq3*10^5)$

輸入描述:

第一行兩個正整數N和M,表示點數和邊數。
接下來M行,每行兩個正整數U和V表示一條無向邊。


保證給定的圖是連通的。

輸出描述:

輸出一行一個非負整數表示不一定要經過的邊有幾條。
輸入:
5 5
1 2
2 3
3 4
4 5
3 5

輸出:
3

說明:

例如第三條邊,月月和華華可以依次走過第一條、第二條、第五條、第四條邊走過全部的景點,所以第三條邊不一定要經過。同理還有第四條、第五條邊,答案為3。


解題分析:

該無向圖的那些割邊是一定要經過的,否則不能經過所有的點,而那些非割邊,就是不必要的。所以本題就是無向圖求橋的模板題。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5
, M = 3e5+5; struct Edge{int to,nxt;}e[M<<1]; int head[N],dfn[N],low[N]; int n,m,cnt=1,tot; bool bridge[M<<1]; inline void add(int u,int v){ e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt; } void Tarjan(int u,int id){ dfn[u]=low[u]=++tot; for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to; if(!dfn[v]){ Tarjan(v,i); low[u]=min(low[u],low[v]); if(low[v]>dfn[u])bridge[i]=bridge[i^1]=1; //將割邊標記 }else if(i!=(id^1))low[u]=min(low[u],dfn[v]); //i為非搜索樹上的邊,才能用來更新low值 } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v;scanf("%d%d",&u,&v);add(u,v);add(v,u); } Tarjan(1,0); //因為該無向圖圖保證連通,所以只用跑一個點就行 int ans=0; for(int i=2;i<cnt;i+=2)if(bridge[i])++ans; printf("%d\n",m-ans); }


Newcoder contest 392 I 逛公園 (無向圖割邊模板)