bzoj5329: [Sdoi2018]战略游戏
大家都说是裸题。。。
圆方树把图变成树,看虚树上有多少圆点即可
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<vector> using namespace std; const int _=1e2; const int maxn=1e5+_; const int maxm=2*1e5+_; int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();} return x*f; } void write(int x) { if(x>=10)write(x/10); putchar(x%10+'0'); } struct node { int x,y,next; }a[2*2*maxm];int len,last[2*maxn]; void ins(int x,int y) { // printf("%d %d\n",x,y); len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } //-----------------------------------------def---------------------------------------------------- int vz,dfn[maxn],low[maxn]; int top,sta[2*2*maxn]; int cnt;vector<int>vec[maxn]; void V_DCC(int x) { dfn[x]=low[x]=++vz; sta[++top]=x; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(dfn[y]==0) { V_DCC(y); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]) { cnt++;vec[cnt].clear(); int i; do { i=sta[top];top--; vec[cnt].push_back(i); }while(i!=y); vec[cnt].push_back(x); } } else low[x]=min(low[x],dfn[y]); } } void maketree(int id) { len=1;memset(last,0,sizeof(last)); for(int i=1;i<=cnt;i++) { id++; for(int j=0;j<vec[i].size();j++) ins(id,vec[i][j]),ins(vec[i][j],id); } } //-----------------------------------------------composition------------------------------------------ int lim,num[2*maxn]; int z,ys[2*maxn]; int fa[30][2*maxn],dep[2*maxn]; void dfs(int x) { for(int i=1;(1<<i)<=dep[x];i++)fa[i][x]=fa[i-1][fa[i-1][x]]; ys[x]=++z; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa[0][x]) { fa[0][y]=x; dep[y]=dep[x]+1; num[y]=num[x]+(y<=lim); dfs(y); } } } int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=25;i>=0;i--) if(dep[x]-dep[y]>=(1<<i))x=fa[i][x]; if(x==y)return x; for(int i=25;i>=0;i--) if(dep[x]>=(1<<i)&&fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y]; return fa[0][x]; } //-----------------------------------------------prepare-------------------------------------------- int p[maxn],ans; bool cmp(int p1,int p2){return ys[p1]<ys[p2];} void VirtualTree(int m) { sort(p+1,p+m+1,cmp); top=1;sta[top]=p[1]; for(int i=2;i<=m;i++) { if(LCA(p[i],sta[top])==sta[top]) {sta[++top]=p[i];continue;} while(top>1&&LCA(p[i],sta[top-1])!=sta[top-1]) ans+=num[sta[top]]-num[sta[top-1]],top--; if(top==1||LCA(p[i],sta[top])!=sta[top-1]) { int lca=LCA(p[i],sta[top]); ans+=num[sta[top]]-num[lca],top--; sta[++top]=lca; sta[++top]=p[i]; } else { ans+=num[sta[top]]-num[sta[top-1]],top--; sta[++top]=p[i]; } } while(top>1) ans+=num[sta[top]]-num[sta[top-1]],top--; ans+=num[sta[top]]-num[fa[0][sta[top]]]; } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; T=read(); while(T--) { int n,m,x,y; n=read(),m=read(); len=1;memset(last,0,sizeof(last)); for(int i=1;i<=m;i++) { x=read(),y=read(); ins(x,y),ins(y,x); } // puts(""); vz=top=cnt=0; memset(dfn,0,sizeof(dfn)); V_DCC(1); maketree(n); num[1]=1;lim=n;dfs(1); // puts(""); //....pre..... int Q; Q=read(); while(Q--) { m=read(); for(int i=1;i<=m;i++)p[i]=read(); ans=0; VirtualTree(m); write(ans-m),putchar('\n'); } // break; } return 0; }
pain and happy in the cruel world.