割点的概念:对于无向图,删除这个点与其相连的边,整个图的连通分量个数增加。
对于无向图的tarjan算法,必须要设前驱~
求割点的模板~
#include#include #include #include #include using namespace std; const int maxn=1014; vector<int> g[maxn]; int N,M,x,y; int low[maxn]; int dfn[maxn]; int cnt; int scc; int pos[maxn]; int isGedian[maxn]; int isRoot[maxn]; stack<int> st; void init () { fill (low,low+maxn,0); fill (dfn,dfn+maxn,0); fill (pos,pos+maxn,0); fill (isGedian,isGedian+maxn,0); for (int i=0;i ) g[i].clear(); while (!st.empty()) st.pop(); cnt=0; scc=0; } void tarjan (int x,int pre) { low[x]=dfn[x]=++cnt; int son=0; st.push(x); for (int i=0;i ) { if (g[x][i]==pre) continue; if (!low[g[x][i]]) { son++; tarjan(g[x][i],x); low[x]=min(low[x],low[g[x][i]]); if (x!=pre&&dfn[x]<=low[g[x][i]]) isGedian[x]=1; } else if (!pos[g[x][i]]) low[x]=min(low[x],dfn[g[x][i]]); } if (low[x]==dfn[x]) { scc++; while (1) { int u=st.top(); st.pop(); low[u]=low[x]; pos[u]=scc; if (u==x) break; } } if (x==pre&&son>1) isGedian[x]=1; } int main () { while (scanf("%d",&N)&&N) { init (); while (scanf("%d",&x)&&x) { char ch; while ((ch=getchar())!='\n') { scanf ("%d",&y); g[x].push_back(y); g[y].push_back(x); } } for (int i=1;i<=N;i++) if (!low[i]) tarjan(i,i); int gedian=0; for (int i=1;i<=N;i++) if (isGedian[i]) gedian++; printf ("%d\n",gedian); } return 0; }