【HDOJ6604】Blow up the city(支配树)

题意:给定一个n点m边的DAG,将只有入边的点称为周驿东点

q次询问,每次给定a,b两点,询问删去某个点x和其相连的所有边,能使a,b至少其中之一不能到达任何周驿东点的x的个数

n,q<=1e5,m<=2e5

思路:

 

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 #define N  210000
 10 #define M  1100000
 11 #define fi first
 12 #define se second
 13 #define MP make_pair
 14 #define pi acos(-1)
 15 #define mem(a,b) memset(a,b,sizeof(a))
 16 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 17 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 18 #define lowbit(x) x&(-x)
 19 #define Rand (rand()*(1<<16)+rand())
 20 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 21 #define ls p<<1
 22 #define rs p<<1|1
 23 
 24 const ll MOD=998244353,inv2=(MOD+1)/2;
 25       double eps=1e-6;
 26       ll INF=1e14;
 27 
 28 vector<int> dom[N],be[N];
 29 int f[N][20],head[N],vet[N],nxt[N],dep[N],ind[N],
 30     id[N],semi[N],p[N],pa[N],dfn[N],idom[N],mn[N],tot,cnt;
 31 
 32 int read()
 33 {
 34    int v=0,f=1;
 35    char c=getchar();
 36    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 37    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 38    return v*f;
 39 }
 40 
 41 void add(int a,int b)
 42 {
 43     nxt[++tot]=head[a];
 44     vet[tot]=b;
 45     head[a]=tot;
 46 }
 47 
 48 void dfs(int u)
 49 {
 50     dfn[u]=++cnt; id[cnt]=u;
 51     int e=head[u];
 52     while(e)
 53     {
 54         int v=vet[e];
 55         if(!dfn[v])
 56         {
 57             dfs(v);
 58             pa[dfn[v]]=dfn[u];
 59         }
 60         be[dfn[v]].push_back(dfn[u]);
 61         e=nxt[e];
 62     }
 63 }
 64 
 65 int get(int x)
 66 {
 67     if(p[x]!=p[p[x]])
 68     {
 69         if(semi[mn[x]]>semi[get(p[x])]) mn[x]=get(p[x]);
 70         p[x]=p[p[x]];
 71     }
 72     return mn[x];
 73 }
 74 
 75 void LT()
 76 {
 77     per(i,cnt,2)
 78     {
 79         for(int j:be[i]) semi[i]=min(semi[i],semi[get(j)]);
 80         dom[semi[i]].push_back(i);
 81         int x=p[i]=pa[i];
 82         for(int y:dom[x]) idom[y]=(semi[get(y)]<x?get(y):x);
 83         dom[x].clear();
 84     }
 85     rep(i,2,cnt)
 86     {
 87         if(idom[i]!=semi[i]) idom[i]=idom[idom[i]];
 88         dom[id[idom[i]]].push_back(id[i]);
 89     }
 90 }
 91 
 92 void getdep(int u,int fa)
 93 {
 94     rep(i,1,19) f[u][i]=f[f[u][i-1]][i-1];
 95     int e=head[u];
 96     while(e)
 97     {
 98         int v=vet[e];
 99         if(v!=fa)
100         {
101             f[v][0]=u;
102             dep[v]=dep[u]+1;
103             getdep(v,u);
104         }
105         e=nxt[e];
106     }
107 }
108 
109 int lca(int x,int y)
110 {
111     if(dep[x]<dep[y]) swap(x,y);
112     int d=dep[x]-dep[y];
113     rep(i,0,19)
114      if((d>>i)&1) x=f[x][i];
115     per(i,19,0)
116      if(f[x][i]!=f[y][i])
117      {
118          x=f[x][i];
119          y=f[y][i];
120      }
121     if(x==y) return x;
122     return f[x][0];
123 }
124 
125 int main()
126 {
127     //freopen("1.in","r",stdin);
128     //freopen("1.out","w",stdout);
129     int cas=read();
130     while(cas--)
131     {
132         int n=read(),m=read();
133         tot=0;
134         rep(i,1,n+1) head[i]=ind[i]=dfn[i]=id[i]=idom[i]=0;
135         rep(i,1,m)
136         {
137             int x=read(),y=read();
138             add(y,x);
139             ind[x]++;
140         }
141         int root=n+1;
142         rep(i,1,n)
143          if(!ind[i]) add(root,i);
144         rep(i,1,root)
145         {
146             dfn[i]=0;
147             dom[i].clear();
148             be[i].clear();
149             p[i]=mn[i]=semi[i]=i;
150         }
151         cnt=0;
152         dfs(root);
153         LT();
154         tot=0;
155         rep(i,1,root) head[i]=0;
156         rep(i,1,root)
157          if(id[idom[i]]) add(id[idom[i]],id[i]);
158         rep(i,1,root) dep[i]=0;
159         getdep(root,0);
160         int q=read();
161         while(q--)
162         {
163             int x=read(),y=read();
164             int t=lca(x,y);
165             printf("%d\n",dep[x]+dep[y]-dep[t]);
166         }
167     }
168 
169     return 0;
170 }

 

posted on 2019-09-26 19:20  myx12345  阅读(305)  评论(0编辑  收藏  举报

导航