【POJ3694】Network
阿新 • • 發佈:2019-03-13
else if 給定 std class 不同的 所有 -- 避免 continue
題目大意:給定一個 N 個點,M 條邊的無向圖,支持 Q 次操作,每次可以向該無向圖中加入一條邊,並需要回答當前無向圖中橋的個數。
題解:(暴力:Q 次 Tarjan)
先進行一次 Tarjan 求出當前圖中橋的個數,並求出邊雙聯通分量,縮點之後所有的邊雙聯通分量構成一棵樹。考慮每次向該無向圖中加邊的情況,若新加入的邊的端點在同一個邊雙聯通分量中時,不會對現有的橋產生影響;若新加入邊的端點在位於兩個不同的雙聯通分量中,則對應於縮點之後的樹來說,在樹上的兩個節點之間添加了一條邊,這會導致兩個節點之間的簡單路徑上的所有邊構成的橋均失效,即:從答案中減去樹上兩點之間邊的個數即可。若每次暴力上跳計算答案貢獻,時間復雜度比較高,在這裏采用並查集進行優化,即:每次上跳時,將當前節點合並到其父節點的集合中,可以使得下一次修改時,避免重復經過同樣的路徑。
代碼如下
#include <cstdio> #include <algorithm> #include <memory.h> using namespace std; const int maxv=1e5+10; const int maxe=2e5+10; int T; struct node{ int nxt,to; node(int x=0,int y=0):nxt(x),to(y){} }e[maxe<<1]; int tot=1,head[maxv]; inline void add_edge(int from,int to){ e[++tot]=node(head[from],to),head[from]=tot; } int n,m,q; int dfs_clk,low[maxv],dfn[maxv],dcc,cor[maxv]; bool bridge[maxe<<1]; void read_and_parse(){ for(int i=1,x,y;i<=m;i++){ scanf("%d%d",&x,&y); add_edge(x,y),add_edge(y,x); } } void tarjan(int u,int fe){ low[u]=dfn[u]=++dfs_clk; 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!=(fe^1))low[u]=min(low[u],dfn[v]); } } void dfs(int u){ cor[u]=dcc; for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(bridge[i]||cor[v])continue; dfs(v); } } vector<int> G[maxv]; int dep[maxv],f[maxv][20]; void dfs(int u,int fa){ for(int i=1;i<=18;i++)f[u][i]=f[f[u][i-1]][i-1]; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa)continue; dep[v]=dep[u]+1,f[v][0]=u; dfs(v,u); } } int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=18;~i;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i]; if(x==y)return x; for(int i=18;~i;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0]; } int fa[maxv]; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);} void solve(){ for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0); for(int i=1;i<=n;i++)if(!cor[i])++dcc,dfs(i); for(int i=1;i<=tot;i++){ int x=e[i].to,y=e[i^1].to; if(cor[x]==cor[y])continue; G[cor[x]].push_back(cor[y]); } dfs(1,0); int ans=dcc-1; for(int i=1;i<=dcc;i++)fa[i]=i; printf("Case %d:\n", ++T); scanf("%d",&q); while(q--){ int x,y; scanf("%d%d",&x,&y); x=cor[x],y=cor[y]; int p=lca(x,y); x=find(x); while(dep[x]>dep[p]){ fa[x]=f[x][0]; --ans; x=find(x); } y=find(y); while(dep[y]>dep[p]){ fa[y]=f[y][0]; --ans; y=find(y); } printf("%d\n",ans); } puts(""); } void init(){ for(int i=1;i<=n;i++)dfn[i]=low[i]=dep[i]=cor[i]=head[i]=0; for(int i=1;i<=2*m+1;i++)bridge[i]=0; for(int i=1;i<=n;i++)G[i].clear(); dcc=dfs_clk=0,tot=1; } int main(){ while(scanf("%d%d",&n,&m)&&n){ init(); read_and_parse(); solve(); } return 0; }
【POJ3694】Network