割点与桥
定义
割点:删掉该点后,原连通图分裂为多个子图;
桥:删掉该边后,原连通图分裂为多个子图;
求割点:
#include<stdio.h> #include<string.h> #include<algorithm> #include<vector> using namespace std; const int maxn=150000+10; int dfn[maxn],low[maxn]; bool iscut[maxn]; vector<int>pic[maxn]; int dfs_clock=0; void tarjan(int x,int fa) { int child=0; dfn[x]=low[x]=++dfs_clock; for (int i=0;i<pic[x].size();i++) { int y=pic[x][i]; if (y==fa) continue; if (!dfn[y]) { child++; tarjan(y,x); low[x]=min(low[x],low[y]); if (low[y]>=dfn[x]) iscut[x]=true; } else low[x]=min(low[x],dfn[y]); } if (fa==-1&&child<=1) iscut[x]=false; } int main() { int n,m; scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); pic[x].push_back(y); pic[y].push_back(x); } memset(dfn,0,sizeof(dfn)); memset(iscut,0,sizeof(iscut)); for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,-1); int cnt=0; for (int i=1;i<=n;i++) if (iscut[i]) cnt++; printf("%d\n",cnt); return 0; }
求桥:
#include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; const int maxn=100; vector<int>pic[maxn]; int dfn[maxn],low[maxn]; int dfs_clock=0; void tarjan(int x,int fa) { dfn[x]=low[x]=++dfs_clock; for (int i=0;i<pic[x].size();i++) { int y=pic[x][i]; if (y==fa) continue; if (!dfn[y]) { tarjan(y,x); low[x]=min(low[x],low[y]); } else low[x]=min(low[x],dfn[y]); } if (dfn[x]==low[x]&&fa!=-1) printf("Find Bridge:%d %d\n",fa,x); } int main() { int n,m; scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); pic[x].push_back(y); pic[y].push_back(x); } memset(dfn,0,sizeof(dfn)); for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i,-1); return 0; }
致虚极,守静笃,万物并作,吾以观其复