At the beginning, I used LCT to query and, and then I got down to my knees .... In the future, it will be better to use rmqlca without modifying the graph structure (in fact, I still forget to split tree links, but the query time is really too time-consuming)
In a graph, you can only go through each vertex from the start point to the end point.
Calculate the dual-link component of the source image and then scale it down to a new image. Note. Build a graph of connected components and cut points;
Then add root (for rmqlca ),
Then, you only need to find the final point N-(CNTV [u] + CNTV [v]-2 * CNTV [LCA] + CNT [LCA]-( dist [u] + dist [v]-2 * Dist [LCA])
CNTV [I]: number of root nodes from I to the tree (excluding the last added root nodes, the same below)
Dist [I]: The distance from I to root
As for why, it is because the cut point is added again.
Note that U and V are the same and U and V are not connected.
Simple path
Time Limit: 4000/2000 MS (Java/others) memory limit: 65536/65536 K (Java/Others)
Total submission (s): 810 accepted submission (s): 147
Problem descriptioneverybody knows that totalfrank has absolutely no sense of direction. getting lost in the university or nearly supermarket is very common for him. we always worry about whether he can find his way back into our sweet base whenever he goes out alone for his
Class. in general, if totalfrank get lost again, we need to check his starting point and destination just in order to find out where he cocould be (You know this task is very common for us ).
Unfortunately, poor totalfrank sometimes forgot taking his mobile phone, when this situation happens, we can't get in touch with him. but it is so lucky that totalfrank can remember places where he had gone before in his trip from his starting point and destination
At this trip so that he won't go to such place again (he can't remember places which he had gone during his previous trip ). as we are all familiar with map, we can find out which place he couldn't be.
However, totalfrank can always get lost, doing this same boring work makes us sleepy. so we ask totalfrank for all possible starting point and destination for him, and try to find out how many places he wouldn't be when he chooses any pair of Starting Point
And destination. here comes the problem, since our university's map is so complex (there can be called buildings which can be considered as points in our university, some pair of these point has a way while others hasn't), we need a program to help us work out
This problem.
Inputthe input contains no more than 10 test cases.
For each test case:
The first line between des two integers n (1 <= n <= 100000) and M (0 <= m <= 200000 ). n is the total number of nodes. M is the number of edges.
The next M lines each describe an edge of this graph in the following format:
X (0 <= x <n) y (0 <= Y <n)
It means that there is an edge from point X to point Y. ways are bidirectional and there are no duplicates or self-loop edges.
The next line between des only one integer Q (1 <= q <= 100000) which indicates the total number of queries.
The next Q lines are all in the following format:
A B, which means in this query totalfrank choose a as his starting point and B as his destination.
Outputfor each test case, first you shoshould print "Case # X:" in a line, where X stands for the case number started with 1. then for each query output a line contains a single integer indicating the number of places which he absolutely couldn't be during the simple
Path between his starting point and destination. If there is no simple path between the starting point and destination just output n.
Leave an empty line after each test case.
Sample Input
4 30 11 21 310 24 40 11 21 32 310 2
Sample output
Case #1:1Case #2:0
#pragma comment(linker, "/STACK:102400000,102400000") //。。。。。。#include<iostream>#include<string>#include<cstring>#include<algorithm>#include<cstdio>#include<utility>#include<map>#include<stack>#include<vector>#include<cmath>using namespace std;#define MAXN 301000#define MAXM 5001000struct node{ int to,next;}edge[MAXM];int head[MAXN],en;int n,m;int vis[MAXN],dfn[MAXN],low[MAXN];int col,color[MAXN],cnt[MAXN];vector<int> bcc[MAXN];stack<pair<int,int> > s;map<pair<int,int>,int> mii;void add(int a,int b){ edge[en].to=b; edge[en].next=head[a]; head[a]=en++; edge[en].to=a; edge[en].next=head[b]; head[b]=en++;}int dis;bool iscut[MAXN];void dfs(int u,int fat){ dfn[u]=low[u]=++dis; vis[u]=1; int child=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(!vis[v]) { s.push(make_pair(u,v)); dfs(v,u); child++; low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) { iscut[u]=1; col++;bcc[col].clear(); for(;;) { pair<int ,int> e; e=s.top();s.pop(); if(color[e.first]!=col) { bcc[col].push_back(e.first); color[e.first]=col; } if(color[e.second]!=col) { bcc[col].push_back(e.second); color[e.second]=col; } if(e.first==u&&e.second==v) break; } } } else if(dfn[v]<dfn[u] && v != fat) { s.push(make_pair(u,v)); low[u]=min(low[u],dfn[v]); } if(fat<0 && child==1) iscut[u]=0; }}int l[MAXN],r[MAXN],mm;void tarjan(){ memset(vis,0,sizeof(vis)); memset(color,0,sizeof(color));col=0; memset(iscut,0,sizeof(iscut)); dis=0; while(!s.empty()) s.pop(); for(int i=0;i<n;i++) if(!vis[i]) dfs(i,-1); int tag=col; memset(cnt,0,sizeof(cnt)); for(int i=0;i<n;i++) { if(!iscut[i]) continue; color[i]=++tag; cnt[tag]=1; } mii.clear();mm=0; for(int i=1;i<=col;i++) { cnt[i]=bcc[i].size(); for(int j=0;j<bcc[i].size();j++) { int v; v=bcc[i][j]; if(!iscut[v]) { color[v]=i; continue; } if(mii.count(make_pair(i,color[v]))==0) { l[mm]=i; r[mm++]=color[v]; mii[make_pair(i,color[v])]=1; } } } col=tag;}int head2[MAXN];int lab[MAXN],dep[MAXN],pos[MAXN],p;int dp[MAXN][20]; //minvoid addDag(int u,int v){ edge[en].to=v; edge[en].next=head2[u]; head2[u]=en++; edge[en].to=u; edge[en].next=head2[v]; head2[v]=en++;}void initRMQ(){for(int i=1;i<=p;i++) dp[i][0]=i;int k=floor(log((double)p)/log(2.0));int a,b,z;for(int j=1;j<=k;j++){for(int i=1;i+(1<<j)-1<=p;i++){z=i+(1<<(j-1));a=dp[i][j-1];b=dp[z][j-1];dp[i][j]=(dep[a]<=dep[b]?a:b);}}}int rmqLCA(int i,int j){ if(j<i) swap(i,j);int z=floor(log((double)(j-i+1))/log(2.0));int a,b;a=dp[i][z];b=dp[j-(1<<z)+1][z];return dep[a]<=dep[b]?lab[a]:lab[b];}void dfsLCA(int u,int d){vis[u]=1,dep[p]=d,lab[p]=u;pos[u]=p++;for(int i=head2[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(vis[v]) continue;dfsLCA(v,d+1);dep[p]=d,lab[p++]=u;}}void initLCA(){ memset(vis,0,sizeof(vis)); p=1; for(int i=0;i<=col;i++) { if(vis[i]) continue; dfsLCA(i,0); } p--; initRMQ();}int dist[MAXN],cntV[MAXN];void dfsDP(int u,int x,int y){ vis[u]=1; dist[u]=x;cntV[u]=y+cnt[u]; for(int i=head2[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(vis[v]) continue; dfsDP(v,x+1,y+cnt[u]); }}void initDP(){ memset(head2,-1,sizeof(head)); for(int i=0;i<mm;i++) addDag(l[i],r[i]); memset(vis,0,sizeof(vis)); for(int i=1;i<=col;i++) { if(vis[i]) continue; dfsDP(i,0,0); addDag(0,i); }}int cs;void solve(){ int q; int u,v; scanf("%d",&q); printf("Case #%d:\n",cs++); for(int i=0;i<q;i++) { scanf("%d%d",&u,&v); int lca=rmqLCA(pos[color[u]],pos[color[v]]); if(u==v) printf("%d\n",n-1); else if(lca==0) printf("%d\n",n); else { u=color[u],v=color[v]; int ans=cntV[u]+cntV[v]-2*cntV[lca]+cnt[lca]-(dist[u]+dist[v]-2*dist[lca]); printf("%d\n",n-ans); } } printf("\n");}int main(){ cs=1; int u,v,ans; while(~scanf("%d%d",&n,&m)) { memset(head,-1,sizeof(head));en=0; for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); } tarjan(); initDP(); initLCA(); solve(); } return 0;}