题解
1001 Azshara's deep sea
Unsolved.
1002 Blow up the city.
题解:倒着建图,然后将原图出度为零的点用一个新节点连接起来,支配树板题。
参考代码:
#include<bits/stdc++.h> using namespace std; #define LL long long #define pb push_back //DAG图q个询问,给你u,v:去掉一个点连同和这个点相连的所有边使得u或v不能到达出度为零的点的方案 const int maxn=2e5+7; int n,m,deg[maxn],rt,a[maxn],dep[maxn],val[maxn]; int f[maxn][20]; vector<int>E[maxn],RE[maxn]; void Topsort() { queue<int>q; rt=n+1;//图可能不连通,建一个新点连接起来 for(int i=1;i<=n;i++) if(!deg[i]){q.push(i);E[rt].pb(i);RE[i].pb(rt);} int tot=0; while(!q.empty()) { int u=q.front(); q.pop(); a[++tot]=u; for(auto &v:E[u]){if((--deg[v])==0) q.push(v);} } } int LCA(int x,int y) { if(dep[x]>dep[y]) swap(x,y); for(int i=19;i>=0;i--) { if(dep[y]>dep[x]&&dep[f[y][i]]>=dep[x]) y=f[y][i]; } if(x==y) return x; for(int i=19;i>=0;i--) { if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; } return f[x][0]; } void Work() { dep[rt]=1; for(int i=1;i<=n;i++) { int u=a[i],fa=-1; for(auto &v:RE[u]) fa=(fa==-1? v:LCA(fa,v)); dep[u]=dep[fa]+1; f[u][0]=fa; for(int i=1;i<=19;i++) f[u][i]=f[f[u][i-1]][i-1]; } } int main() { int tt; scanf("%d",&tt); while(tt--) { scanf("%d%d",&n,&m); memset(f,0,sizeof(f)); for(int i=1;i<=n+1;i++) { E[i].clear(); RE[i].clear(); dep[i]=deg[i]=0; } while(m--) { int u, v; scanf("%d%d", &u, &v); E[v].pb(u); RE[u].pb(v); deg[u]++; } Topsort(); Work(); int q; scanf("%d", &q); while(q--) { int u, v; scanf("%d%d",&u,&v); int lca=LCA(u,v); printf("%d\n",dep[u]+dep[v]-dep[lca]-1); } } return 0; }