UVALive-4839 HDU-3686 Traffic Real Time Query System 题解

题目大意:

  有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个。

思路:

  先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求LCA计算。

  注意:数组范围。

代码:

  1 #include<cstdio>
  2 #include<vector>
  3 #include<iostream>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N=10009,M=100009;
  7 int u[M<<1],v[M<<1],nex[M<<1],id[M<<1],hea[N<<1],dfn[N<<1],low[N],st[M],sub[N],edge[M],
  8     fa[N<<2][20],f[N<<2],pos[N<<2],dep[N<<1];
  9 bool vis[M<<1],iscut[N],treecut[N<<1];
 10 int tim,top,tot,cnt,num;
 11 vector <int> belo[N];
 12 
 13 int read()
 14 {
 15     int x=0; char ch=getchar();
 16     while (ch<'0' || ch>'9') ch=getchar();
 17     while (ch>='0' && ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
 18     return x;
 19 }
 20 
 21 void add(int x,int y) { v[cnt]=y,u[cnt]=x,nex[cnt]=hea[x],vis[cnt]=0,hea[x]=cnt++; }
 22 
 23 void tarjan(int x)
 24 {
 25     dfn[x]=low[x]=++tim;
 26     for (int i=hea[x];~i;i=nex[i])
 27         if (!vis[i])
 28         {
 29             int y=v[i]; st[++top]=i;
 30             vis[i]=vis[i^1]=1;
 31             if (!dfn[y])
 32             {
 33                 tarjan(y);
 34                 low[x]=min(low[x],low[y]);
 35                 if (low[y]>=dfn[x])
 36                 {
 37                     ++sub[x],++num;
 38                     iscut[x]=1;
 39                     do
 40                     {
 41                         int now=st[top--];
 42                         belo[u[now]].push_back(num);
 43                         belo[v[now]].push_back(num);
 44                         edge[id[now]]=num;
 45                         y=u[now];
 46                     }while (y^x);
 47                 }
 48             }
 49             else low[x]=min(low[x],dfn[y]);
 50         }
 51 }
 52 
 53 void dfs(int x)
 54 {
 55     dfn[x]=++tim; fa[++tot][0]=dfn[x];
 56     f[tim]=x; pos[x]=tot;
 57     for (int i=hea[x];~i;i=nex[i])
 58     {
 59         int y=v[i];
 60         if (!dfn[y])
 61         {
 62             dep[y]=dep[x]+treecut[x];
 63             dfs(y);    fa[++tot][0]=dfn[x];
 64         }
 65     }
 66 }
 67 
 68 void RMQ(int n)
 69 {
 70     for (int j=1;(1<<j)<=n;++j)
 71         for (int i=1;i+j-1<=n;++i)
 72             fa[i][j]=min(fa[i][j-1],fa[i+(1<<j-1)][j-1]);
 73 }
 74 
 75 int lca(int x,int y)
 76 {
 77     if (pos[x]<pos[y]) swap(x,y);
 78     int k=0;
 79     while (1<<(k+1)<=pos[x]-pos[y]+1) ++k;
 80     return f[min(fa[pos[y]][k],fa[pos[x]-(1<<k)+1][k])];
 81 }
 82 
 83 void wk(int n)
 84 {
 85     int i,m,x,y;
 86     for (tim=tot=i=0;i<=n;++i) dfn[i]=0;
 87     for (i=1;i<=n;++i)
 88         if (!dfn[i]) dep[i]=0,dfs(i);
 89     RMQ(tot);
 90     for (m=read();m--;)
 91     {
 92         x=edge[read()],y=edge[read()];
 93         if (x<0 || y<0) { puts("0"); continue; }
 94         int z=lca(x,y);
 95         if (x==z) printf("%d
",dep[y]-dep[x]-treecut[x]);
 96         else if (y==z) printf("%d
",dep[x]-dep[y]-treecut[y]);
 97              else printf("%d
",dep[x]+dep[y]-(dep[z]<<1)-treecut[z]);
 98     }
 99 }
100 
101 int main()
102 {
103     int n,m;
104     while (~scanf("%d%d",&n,&m))
105     {
106         int i; cnt=top=num=tim=0;
107         if (!(n+m)) break;
108         for (i=0;i<=n;++i) hea[i]=-1,dfn[i]=sub[i]=iscut[i]=0,belo[i].clear();
109         for (i=1;i<=m;++i)
110         {
111             int x=read(),y=read();
112             id[cnt]=i,add(x,y),id[cnt]=i,add(y,x);
113         }
114         for (i=1;i<=n;++i)
115             if (!dfn[i])
116             {
117                 tarjan(i);
118                 if (--sub[i]<=0) iscut[i]=0;
119             }
120         for (i=1;i<=num;++i) treecut[i]=0;
121         for (i=1;i<=num+n;++i) hea[i]=-1;
122         cnt=0;
123         for (i=1;i<=n;++i)
124             if (iscut[i])
125             {
126                 sort(belo[i].begin(),belo[i].end());
127                 treecut[++num]=1;
128                 add(belo[i][0],num),add(num,belo[i][0]);
129                 for (int j=1;j<belo[i].size();++j)
130                     if (belo[i][j]^belo[i][j-1]) add(belo[i][j],num),add(num,belo[i][j]);
131             }
132         wk(num);
133     }
134     return 0;
135 }
原文地址:https://www.cnblogs.com/HHshy/p/6159332.html