2 条题解
-
112322132131231 (褚战) LV 10 @ 2023-07-12 17:41:00
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXSIZE=100000020; int bufpos; char buf[MAXSIZE]; #define NEG 0 void init(){ #ifdef LOCAL freopen("5329.txt","r",stdin); freopen("5329.out","w",stdout); #endif buf[fread(buf,1,MAXSIZE,stdin)]='\0'; bufpos=0; } #if NEG int readint(){ bool isneg; int val=0; for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++); bufpos+=(isneg=buf[bufpos]=='-'); for(;isdigit(buf[bufpos]);bufpos++) val=val*10+buf[bufpos]-'0'; return isneg?-val:val; } #else int readint(){ int val=0; for(;!isdigit(buf[bufpos]);bufpos++); for(;isdigit(buf[bufpos]);bufpos++) val=val*10+buf[bufpos]-'0'; return val; } #endif char readchar(){ for(;isspace(buf[bufpos]);bufpos++); return buf[bufpos++]; } int readstr(char* s){ int cur=0; for(;isspace(buf[bufpos]);bufpos++); for(;!isspace(buf[bufpos]);bufpos++) s[cur++]=buf[bufpos]; s[cur]='\0'; return cur; } const int maxn=400002; const int maxm=800002; struct graph{ int n,m; struct edge{ int to,next; }e[maxm]; int first[maxn]; void addedge(int from,int to){ e[++m]=(edge){to,first[from]}; first[from]=m; } }; struct block_cut_tree : graph{ bool cir[maxn]; int sz[maxn],fa[maxn],top[maxn],son[maxn],st[maxn],en[maxn],dist[maxn],dep[maxn],cl; void init(){ memset(first,0,(n+1)*4); memset(cir,0,n+1); m=0; } void dfs(int u){ st[u]=++cl; sz[u]=1; for(int i=first[u];i;i=e[i].next){ int v=e[i].to; if (st[v]) continue; dist[v]=dist[u]+cir[v]; fa[v]=u; dep[v]=dep[u]+1; dfs(v); sz[u]+=sz[v]; if (sz[v]>sz[son[u]]) son[u]=v; } en[u]=cl; } void dfs2(int u,int tp){ top[u]=tp; if (son[u]) dfs2(son[u],tp); for(int i=first[u];i;i=e[i].next){ int v=e[i].to; if (!top[v]) dfs2(v,v); } } void pre(){ memset(son,0,(n+1)*4); memset(top,0,(n+1)*4); memset(st,0,(n+1)*4); cl=0; dist[1]=cir[1]; dfs(1); dfs2(1,1); } int lca(int u,int v){ for(;top[u]!=top[v];u=fa[top[u]]) if (dep[top[u]]<dep[top[v]]) swap(u,v); return dep[u]<dep[v]?u:v; } pair<int,int> b[maxn*2]; int stk[maxn*2],tp; int work(int* a,int cnt){ int sum=-cnt; for(int i=1;i<=cnt;i++) b[i]=make_pair(st[a[i]],a[i]); sort(b+1,b+cnt+1); for(int i=cnt-1;i;i--){ int u=lca(b[i].second,b[i+1].second); b[++cnt]=make_pair(st[u],u); } sort(b+1,b+cnt+1); cnt=unique(b+1,b+cnt+1)-b-1; tp=0; for(int i=1;i<=cnt;i++){ int u=b[i].second; while(tp && (st[u]<st[stk[tp]] || en[u]>en[stk[tp]])) tp--; if (tp) sum+=dist[u]-dist[stk[tp]]; stk[++tp]=u; } if (cir[b[1].second]) sum++; return sum; } }t; struct bcc_graph : graph{ int low[maxn],dfn[maxn],cl,cnt; int stk[maxn],tp; void init(int n){ this->n=n; memset(first,0,(n+1)*4); m=0; } void dfs(int u,int fa){ low[u]=dfn[u]=++cl; stk[++tp]=u; bool qwq=0; for(int i=first[u];i;i=e[i].next){ int v=e[i].to; if (v==fa && !qwq){ qwq=1; continue; } if (dfn[v]){ low[u]=min(low[u],dfn[v]); continue; } dfs(v,u); low[u]=min(low[u],low[v]); if (low[v]>=dfn[u]){ cnt++; t.addedge(u,cnt); for(;;){ int now=stk[tp--]; t.addedge(cnt,now); if (now==v) break; } } } } void build(){ cnt=n; memset(low,0,(n+1)*4); memset(dfn,0,(n+1)*4); cl=tp=0; t.init(); dfs(1,0); t.n=cnt; for(int i=1;i<=n;i++) t.cir[i]=1; t.pre(); } }g; int a[maxn]; int main(){ int size = 32 << 20; // 32MB char *p = (char *)malloc(size) + size; __asm__ __volatile__("movq %0, %%rsp\n" :: "r"(p)); init(); int T=readint(); while(T--){ int n=readint(),m=readint(); g.init(n); while(m--){ int u=readint(),v=readint(); g.addedge(u,v); g.addedge(v,u); } g.build(); int q=readint(); while(q--){ int k=readint(); for(int i=1;i<=k;i++) a[i]=readint(); printf("%d\n",t.work(a,k)); } } exit(0); }
-
02018-06-03 21:29:47@
建出原图的圆方树(求点双时需要判下重边),对于每个询问,虚树上的圆点个数减去输入的点个数就是答案。
注意Vijos的栈空间很小,所以需要手写栈或者黑科技(参见代码)。#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXSIZE=100000020; int bufpos; char buf[MAXSIZE]; #define NEG 0 void init(){ #ifdef LOCAL freopen("5329.txt","r",stdin); freopen("5329.out","w",stdout); #endif buf[fread(buf,1,MAXSIZE,stdin)]='\0'; bufpos=0; } #if NEG int readint(){ bool isneg; int val=0; for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++); bufpos+=(isneg=buf[bufpos]=='-'); for(;isdigit(buf[bufpos]);bufpos++) val=val*10+buf[bufpos]-'0'; return isneg?-val:val; } #else int readint(){ int val=0; for(;!isdigit(buf[bufpos]);bufpos++); for(;isdigit(buf[bufpos]);bufpos++) val=val*10+buf[bufpos]-'0'; return val; } #endif char readchar(){ for(;isspace(buf[bufpos]);bufpos++); return buf[bufpos++]; } int readstr(char* s){ int cur=0; for(;isspace(buf[bufpos]);bufpos++); for(;!isspace(buf[bufpos]);bufpos++) s[cur++]=buf[bufpos]; s[cur]='\0'; return cur; } const int maxn=400002; const int maxm=800002; struct graph{ int n,m; struct edge{ int to,next; }e[maxm]; int first[maxn]; void addedge(int from,int to){ e[++m]=(edge){to,first[from]}; first[from]=m; } }; struct block_cut_tree : graph{ bool cir[maxn]; int sz[maxn],fa[maxn],top[maxn],son[maxn],st[maxn],en[maxn],dist[maxn],dep[maxn],cl; void init(){ memset(first,0,(n+1)*4); memset(cir,0,n+1); m=0; } void dfs(int u){ st[u]=++cl; sz[u]=1; for(int i=first[u];i;i=e[i].next){ int v=e[i].to; if (st[v]) continue; dist[v]=dist[u]+cir[v]; fa[v]=u; dep[v]=dep[u]+1; dfs(v); sz[u]+=sz[v]; if (sz[v]>sz[son[u]]) son[u]=v; } en[u]=cl; } void dfs2(int u,int tp){ top[u]=tp; if (son[u]) dfs2(son[u],tp); for(int i=first[u];i;i=e[i].next){ int v=e[i].to; if (!top[v]) dfs2(v,v); } } void pre(){ memset(son,0,(n+1)*4); memset(top,0,(n+1)*4); memset(st,0,(n+1)*4); cl=0; dist[1]=cir[1]; dfs(1); dfs2(1,1); } int lca(int u,int v){ for(;top[u]!=top[v];u=fa[top[u]]) if (dep[top[u]]<dep[top[v]]) swap(u,v); return dep[u]<dep[v]?u:v; } pair<int,int> b[maxn*2]; int stk[maxn*2],tp; int work(int* a,int cnt){ int sum=-cnt; for(int i=1;i<=cnt;i++) b[i]=make_pair(st[a[i]],a[i]); sort(b+1,b+cnt+1); for(int i=cnt-1;i;i--){ int u=lca(b[i].second,b[i+1].second); b[++cnt]=make_pair(st[u],u); } sort(b+1,b+cnt+1); cnt=unique(b+1,b+cnt+1)-b-1; tp=0; for(int i=1;i<=cnt;i++){ int u=b[i].second; while(tp && (st[u]<st[stk[tp]] || en[u]>en[stk[tp]])) tp--; if (tp) sum+=dist[u]-dist[stk[tp]]; stk[++tp]=u; } if (cir[b[1].second]) sum++; return sum; } }t; struct bcc_graph : graph{ int low[maxn],dfn[maxn],cl,cnt; int stk[maxn],tp; void init(int n){ this->n=n; memset(first,0,(n+1)*4); m=0; } void dfs(int u,int fa){ low[u]=dfn[u]=++cl; stk[++tp]=u; bool qwq=0; for(int i=first[u];i;i=e[i].next){ int v=e[i].to; if (v==fa && !qwq){ qwq=1; continue; } if (dfn[v]){ low[u]=min(low[u],dfn[v]); continue; } dfs(v,u); low[u]=min(low[u],low[v]); if (low[v]>=dfn[u]){ cnt++; t.addedge(u,cnt); for(;;){ int now=stk[tp--]; t.addedge(cnt,now); if (now==v) break; } } } } void build(){ cnt=n; memset(low,0,(n+1)*4); memset(dfn,0,(n+1)*4); cl=tp=0; t.init(); dfs(1,0); t.n=cnt; for(int i=1;i<=n;i++) t.cir[i]=1; t.pre(); } }g; int a[maxn]; int main(){ int size = 32 << 20; // 32MB char *p = (char *)malloc(size) + size; __asm__ __volatile__("movq %0, %%rsp\n" :: "r"(p)); init(); int T=readint(); while(T--){ int n=readint(),m=readint(); g.init(n); while(m--){ int u=readint(),v=readint(); g.addedge(u,v); g.addedge(v,u); } g.build(); int q=readint(); while(q--){ int k=readint(); for(int i=1;i<=k;i++) a[i]=readint(); printf("%d\n",t.work(a,k)); } } exit(0); }
- 1
信息
- ID
- 2045
- 难度
- 6
- 分类
- (无)
- 标签
- 递交数
- 55
- 已通过
- 19
- 通过率
- 35%
- 被复制
- 3
- 上传者