LCA+树上差分,和之前类似的题差不多,就是多了个v-dcc缩点,唯一要注意的就是判断是否是割点,对于不是割点的点,如果他是起点或重点,ans++,和差分没有关系,对于割点,则需要用到差分,注意割点与非割点的答案要分开存储,否则会死的。
另外要注意的是数组的大小,开始我因为数组开小了然后MLE了(对,就是这么神奇),因为如果退化成一条链,缩完点后的点数会比缩点前还要多。
#include<iostream> #include<cstdio> #include<vector> #define MAXN 300010 using namespace std; struct edge { int u,v,nxt; #define u(x) ed[x].u #define v(x) ed[x].v #define n(x) ed[x].nxt #define u2(x) ed2[x].u #define v2(x) ed2[x].v #define n2(x) ed2[x].nxt }ed[MAXN*4],ed2[MAXN*4]; int first[MAXN],num_e; #define f(x) first[x] int first2[MAXN],num_e2; #define f2(x) first2[x] int n,m,q; int dfn[MAXN],low[MAXN],num,root; int stack[MAXN],top,cnt; bool iscut[MAXN]; vector<int> dcc[MAXN]; void tarjan(int x) { dfn[x]=low[x]=++num; stack[++top]=x; if(x==root&&!f(x)){dcc[++cnt].push_back(x);return;} int flag=0; for(int i=f(x);i;i=n(i)) if(!dfn[v(i)]) { tarjan(v(i));low[x]=min(low[x],low[v(i)]); if(low[v(i)]>=dfn[x]) { flag++; if(x!=root||flag>1)iscut[x]=1; cnt++;int z; do{dcc[cnt].push_back(z=stack[top--]);}while(z!=v(i)); dcc[cnt].push_back(x); } } else low[x]=min(low[x],dfn[v(i)]); } int new_id[MAXN],c[MAXN]; int f[MAXN][20],dep[MAXN]; void dfs(int x,int fa,int deep) { f[x][0]=fa;dep[x]=deep; for(int i=f2(x);i;i=n2(i)) if(v2(i)!=fa) dfs(v2(i),x,deep+1); } int ans[MAXN],eans[MAXN]; void dfs2(int x,int fa) { for(int i=f2(x);i;i=n2(i)) if(v2(i)!=fa) { dfs2(v2(i),x); eans[x]+=eans[v2(i)]; } } int LCA(int x,int y) { if(dep[x]>dep[y])swap(x,y); while(dep[x]!=dep[y]) for(int i=0;;i++) if(dep[f[y][i]]<dep[x]) {y=f[y][i-1];break;} if(x==y)return x; while(f[x][0]!=f[y][0]) for(int i=0;;i++) if(f[x][i]==f[y][i]) {x=f[x][i-1],y=f[y][i-1];break;} return f[x][0]; } inline void add(int u,int v); inline void add2(int u,int v); signed main() { // freopen("in.txt","r",stdin); scanf("%d%d%d",&n,&m,&q); int a,b; for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); add(a,b),add(b,a); } for(int i=1;i<=n;i++) if(!dfn[i]){root=i;tarjan(i);} num=cnt; for(int i=1;i<=n;i++) if(iscut[i])new_id[i]=++num; for(int i=1;i<=cnt;i++) for(int j=0;j<dcc[i].size();j++) { int x=dcc[i][j]; if(iscut[x]) add2(i,new_id[x]),add2(new_id[x],i); else c[dcc[i][j]]=i; } dfs(1,0,1); for(int j=1;j<20;j++) for(int i=1;i<=num;i++) f[i][j]=f[f[i][j-1]][j-1]; for(int i=1;i<=q;i++) { scanf("%d%d",&a,&b); if(!iscut[a])ans[a]++; if(!iscut[b])ans[b]++; int ca=iscut[a]?new_id[a]:c[a], cb=iscut[b]?new_id[b]:c[b], lca=LCA(ca,cb); eans[ca]++,eans[cb]++; eans[f[lca][0]]--,eans[lca]--; } dfs2(1,0); for(int i=1;i<=n;i++) printf("%d ",iscut[i]?eans[new_id[i]]:ans[i]); } inline void add(int u,int v) { ++num_e; u(num_e)=u; v(num_e)=v; n(num_e)=f(u); f(u)=num_e; } inline void add2(int u,int v) { ++num_e2; u2(num_e2)=u; v2(num_e2)=v; n2(num_e2)=f2(u); f2(u)=num_e2; }