Traffic Real Time Query System HDU - 3686

https://vjudge.net/problem/HDU-3686

点双啊,就是在求割顶的时候,另外用一个栈来存一些

在遍历u点出发的边时,遇到树边或反向边(u,v)就把此边加入栈(可能要记一下边的编号)(但是,如果(u,v)是反过来看的反向边(此时dfn[v]>=dfn[u];实际反向边应该为(v,u))或者反过来的树边(此时k==(last^1))就不能加入)

遇到一个割点,就多一个点双(不考虑因为(fa<0&&child==1)的特判而去掉的割点)

计算(u,v)中遇到割点后,就不断从栈顶弹出边,直到栈顶的边与(u,v)相等,然后再弹出一个边;所有这些弹出的边以及边的两个端点都属于这个点双

先对原图求点双连通分量,求出每条边属于的点双

然后为原图中每一个点双新建一个点,向这个点双内每一个点连边,去掉原图所有边,得到一个新图(实际上是一棵树)

询问两条边a,b时,先找出它们属于的点双对应的点编号x,y,那么答案就是新树上x与y的最短路径中"非点双对应的点"的数量(由于实际是要求这两个点双在原图中的路径间割点数量,而只有割点才可能成为新树中要统计的点)

https://blog.csdn.net/u013480600/article/details/44835827

错误记录:

倍增写错。。。115行少d[anc[x][0]][0]

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<vector>
  5 using namespace std;
  6 #define fi first
  7 #define se second
  8 #define mp make_pair
  9 #define pb push_back
 10 typedef long long ll;
 11 typedef unsigned long long ull;
 12 typedef pair<int,int> pii;
 13 #define CLR(x) memset(x,0,sizeof(x))
 14 #define N 10100
 15 #define M 101000
 16 typedef pair<pii,int> ppi;
 17 struct E{int to,nxt;};
 18 namespace G
 19 {
 20 E e[M<<1];
 21 int f1[N],ne;
 22 int dfn[N],bno[N],dfc,cnt,bn2[M];bool iscut[N];
 23 ppi st[M];int top;
 24 vector<int> bcc[N];
 25 //#define D(x) ((x)&2147483646)
 26 void clr()
 27 {
 28     CLR(f1);ne=1;
 29     CLR(dfn);CLR(bno);CLR(iscut);CLR(bn2);dfc=cnt=top=0;
 30 }
 31 void me(int a,int b)
 32 {
 33     e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
 34     e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
 35 }
 36 int dfs(int u,int last)
 37 {
 38     int k,v,lowu=dfn[u]=++dfc,chi=0,lowv;ppi x;
 39     for(k=f1[u];k;k=e[k].nxt)
 40     {
 41         v=e[k].to;
 42         if(!dfn[v])
 43         {
 44             st[++top]=mp(mp(u,v),k);chi++;
 45             lowv=dfs(v,k);lowu=min(lowu,lowv);
 46             if(lowv>=dfn[u])
 47             {
 48                 iscut[u]=1;
 49                 cnt++;bcc[cnt].clear();
 50                 for(;;)
 51                 {
 52                     x=st[top--];
 53                     if(bno[x.fi.fi]!=cnt)
 54                         bno[x.fi.fi]=cnt,bcc[cnt].pb(x.fi.fi);
 55                     if(bno[x.fi.se]!=cnt)
 56                         bno[x.fi.se]=cnt,bcc[cnt].pb(x.fi.se);
 57                     bn2[x.se/2]=cnt;
 58                     if(x.fi.fi==u&&x.fi.se==v)    break;
 59                 }
 60             }
 61         }
 62         else if(dfn[v]<dfn[u]&&k!=(last^1))
 63         {
 64             st[++top]=mp(mp(u,v),k);
 65             lowu=min(lowu,dfn[v]);
 66         }
 67     }
 68     if(last<0&&chi==1)    iscut[u]=0;
 69     return lowu;
 70 }
 71 }
 72 int n,m,l2n=18,qq;
 73 namespace T
 74 {
 75 E e[N<<2];
 76 int f1[N<<1],ne;
 77 int anc[N<<1][22],d[N<<1][22],dep[N<<1];
 78 //d[i][j]表示i点到其2^j级祖先中(含i,不含祖先),共有几个圆点
 79 bool vis[N<<1];
 80 void clr()    {CLR(f1);CLR(anc);CLR(vis);CLR(d);CLR(dep);ne=1;}
 81 void me(int a,int b)
 82 {
 83     e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;
 84     e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;
 85 }
 86 void dfs(int u,int fa)
 87 {
 88     int i;
 89     vis[u]=1;anc[u][0]=fa;d[u][0]=(u<=n);
 90     for(i=1;i<=l2n;i++)
 91     {
 92         anc[u][i]=anc[anc[u][i-1]][i-1];
 93         d[u][i]=d[u][i-1]+d[anc[u][i-1]][i-1];
 94     }
 95     for(int k=f1[u];k;k=e[k].nxt)
 96         if(e[k].to!=fa)
 97         {
 98             dep[e[k].to]=dep[u]+1;
 99             dfs(e[k].to,u);
100         }
101 }
102 int ask(int x,int y)
103 {
104     int t,i,ans=0;
105     if(dep[x]<dep[y])    swap(x,y);
106     for(t=dep[x]-dep[y],i=0;t>0;t>>=1,i++)
107         if(t&1)    ans+=d[x][i],x=anc[x][i];
108     if(x==y)    return ans;
109     for(i=l2n;i>=0;i--)
110         if(anc[x][i]!=anc[y][i])
111         {
112             ans+=(d[x][i]+d[y][i]);
113             x=anc[x][i];y=anc[y][i];
114         }
115     ans+=(d[x][0]+d[y][0]+d[anc[x][0]][0]);
116     return ans;
117 }
118 }
119 int main()
120 {
121     int a,b,i,j;
122     while(1)
123     {
124         G::clr();T::clr();
125         scanf("%d%d",&n,&m);
126         if(n==0&&m==0)    break;
127         for(i=1;i<=m;i++)    scanf("%d%d",&a,&b),G::me(a,b);
128         for(i=1;i<=n;i++)    if(!G::dfn[i])    G::dfs(i,-1);
129         for(i=1;i<=G::cnt;i++)
130             for(j=0;j<G::bcc[i].size();j++)
131                 T::me(n+i,G::bcc[i][j]);
132         for(i=1;i<=n+G::cnt;i++)
133             if(!T::vis[i])
134                 T::dfs(i,0);
135         scanf("%d",&qq);
136         while(qq--)
137         {
138             scanf("%d%d",&a,&b);
139             printf("%d\n",T::ask(n+G::bn2[a],n+G::bn2[b]));
140         }
141     }
142     return 0;
143 }

 

posted @ 2018-07-10 13:17  hehe_54321  阅读(229)  评论(0编辑  收藏  举报
AmazingCounters.com