NC7501D Router Mesh (去掉割点算连通快的变化)
题意:
给出一个图,按序输出去掉第i个点,剩下的连通快数量。
题解:
割点魔改。
#include<cstdio> #include<algorithm> #include<vector> #include<stack> #include<cstring> using namespace std; const int maxn=3e5+100; 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]; int cut[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); fill (cut,cut+maxn,0); for (int i=0;i<maxn;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<g[x].size();i++) { if (g[x][i]==pre) continue; if (!dfn[g[x][i]]) { son++; tarjan(g[x][i],x); low[x]=min(low[x],low[g[x][i]]); if ((low[g[x][i]]>=dfn[x]&&x!=pre)||(son>1&&x==pre)) cut[x]++; } else if (dfn[g[x][i]]<dfn[x]&&g[x][i]!=pre) low[x]=min(low[x],dfn[g[x][i]]); } } int father[maxn]; int size[maxn]; int findfather (int x) { int a=x; while (x!=father[x]) { x=father[x]; } while (a!=father[a]) { int z=a; a=father[a]; father[z]=x; } return x; } void Union (int x,int y) { x=findfather(x); y=findfather(y); father[x]=y; size[y]+=size[x]; } int main () { while (~scanf("%d%d",&N,&M)) { init (); for (int i=1;i<=N;i++) size[i]=1,father[i]=i; for (int i=1;i<=M;i++) { int x,y; scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); Union(x,y); } int sum=0; for (int i=1;i<=N;i++) if (!low[i]) tarjan(i,i),sum++; for (int i=1;i<=N;i++) { //printf("%d %d\n",findfather(i),size[i]); if (findfather(i)==i&&size[i]==1) { printf("%d ",sum-1); } else printf("%d ",sum+cut[i]); } printf("\n"); } return 0; }