POJ3352Road construction(邊雙聯通分量)
阿新 • • 發佈:2018-12-18
大意:
一張無向連通圖 問你 最少新增多少條邊,使得任意兩點之間有兩條無公共邊的路(可以有公共點)
有這樣一個結論:
答案是縮點後所有度數為1的點的數量(num+1)/2
縮點後相當於是一顆樹
考慮對於所有葉子節點
將其兩兩連邊
如果還剩一個則還需要連一條邊
所有我們只需要縮點後統計度數就是了
注意要判重邊
#include<algorithm> #include<cmath> #include<cstring> #include<iostream> #include<cstdlib> #include<cstdio> #include<stack> #include<map> using namespace std; #define ll long long inline int read(){ char ch=getchar(); int res=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return res; } int n,m,adj[50005],nxt[100005],vis[50005],to[100005],in[50005],dfn[50005],low[50005],bel[50005],belnum,ans,cnt=1,tot; stack<int> stk; inline void addedge(int u,int v){ nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v; nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u; } inline void tarjan(int u,int pre){ dfn[u]=low[u]=++tot; stk.push(u); for(int e=adj[u];e;e=nxt[e]){ if((e^1)==pre)continue;//判重邊的騷操作,但注意要把建邊的cnt設為1或-1 int v=to[e]; if(!dfn[v]){ tarjan(v,e); low[u]=min(low[u],low[v]); } else low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ belnum++; int tmp; do{ tmp=stk.top(); bel[tmp]=belnum; stk.pop(); }while(tmp!=u); } } int main(){ n=read(),m=read(); for(int i=1;i<=m;i++){ int u=read(),v=read(); addedge(u,v); } tarjan(1,0); for(int u=1;u<=n;u++){ for(int e=adj[u];e;e=nxt[e]){ int v=to[e]; if(bel[u]!=bel[v]){ in[bel[u]]++; } } } for(int i=1;i<=belnum;i++){ if(in[i]==1)ans++; } cout<<(ans+1)/2; }