题解:
建出圆方树
先求点双,然后每个点向点双代表的方点连边
然后树上差分一下
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<queue> #include<stack> using namespace std; const int maxn=400009; typedef pair<int,int> fuck; int n,m,t; int rx[maxn],ry[maxn]; int cntedge=0; int head[maxn]={0}; int to[maxn<<1],nex[maxn<<1]; void Addedge(int x,int y){ nex[++cntedge]=head[x]; to[cntedge]=y; head[x]=cntedge; } int bcccnt=0,dfsclock=0; int pre[maxn],lowlink[maxn],bccnum[maxn]; stack<fuck>S; vector<int>B[maxn]; void Dfs(int u,int fa){ pre[u]=lowlink[u]=++dfsclock; for(int i=head[u];i;i=nex[i]){ int v=to[i]; if(v==fa)continue; if(!pre[v]){ S.push(make_pair(u,to[i])); Dfs(v,u); lowlink[u]=min(lowlink[u],lowlink[v]); if(lowlink[v]>=pre[u]){ ++bcccnt; for(;;){ pair<int,int>P=S.top();S.pop(); if(bccnum[P.first]!=bcccnt){ bccnum[P.first]=bcccnt; B[bcccnt].push_back(P.first); } if(bccnum[P.second]!=bcccnt){ bccnum[P.second]=bcccnt; B[bcccnt].push_back(P.second); } if(P==make_pair(u,v))break; } } }else{ lowlink[u]=min(lowlink[u],pre[v]); } } } int totn; int f[maxn][20],dep[maxn]; void Dfs2(int x,int fa){ f[x][0]=fa; dep[x]=dep[fa]+1; for(int i=head[x];i;i=nex[i]){ if(to[i]==fa)continue; Dfs2(to[i],x); } } void LCAinit(){ for(int j=1;j<=19;++j){ for(int i=1;i<=totn;++i){ f[i][j]=f[f[i][j-1]][j-1]; } } } int Getlca(int u,int v){ if(dep[u]<dep[v])swap(u,v); for(int j=19;j>=0;--j){ if(dep[f[u][j]]>=dep[v]){ u=f[u][j]; } } if(u==v)return u; for(int j=19;j>=0;--j){ if(f[u][j]!=f[v][j]){ u=f[u][j];v=f[v][j]; } } return f[u][0]; } int mar[maxn]; void Dp(int x,int fa){ for(int i=head[x];i;i=nex[i]){ if(to[i]==fa)continue; Dp(to[i],x); mar[x]+=mar[to[i]]; } } int father[maxn]; int Getf(int x){ if(father[x]==x)return x; return father[x]=Getf(father[x]); } void Unionn(int x,int y){ int fx=Getf(x); int fy=Getf(y); if(fx!=fy)father[fx]=fy; } int main(){ scanf("%d%d%d",&n,&m,&t); for(int i=1;i<=m;++i){ scanf("%d%d",&rx[i],&ry[i]); Addedge(rx[i],ry[i]); Addedge(ry[i],rx[i]); } Dfs(1,0); cntedge=0; memset(head,0,sizeof(head)); totn=n; for(int i=1;i<=n+bcccnt;++i)father[i]=i; for(int u=1;u<=bcccnt;++u){ ++totn; for(int i=0;i<B[u].size();++i){ int v=B[u][i]; Addedge(v,totn); Addedge(totn,v); Unionn(totn,v); } } // for(int i=1;i<=m;++i){ // if(Getf(rx[i])!=Getf(ry[i])){ // Addedge(rx[i],ry[i]); // Addedge(ry[i],rx[i]); // Unionn(rx[i],ry[i]); // } // } Dfs2(1,0); LCAinit(); while(t--){ int x,y; scanf("%d%d",&x,&y); int lca=Getlca(x,y); mar[x]++;mar[y]++;mar[lca]--;mar[f[lca][0]]--; } Dp(1,0); for(int i=1;i<=n;++i)printf("%d\n",mar[i]); return 0; }