Zookeeper

That is to say, we will give you n vertices and n-1 edges to form an undirected graph.

Then there are m inquiries, asking you the shortest distance between the two points each time.

So it is converted to the shortest-circuit problem?

Well, there can be a maximum of 40 thousand vertices. The number of edges is 40 thousand,

Therefore, spfa is used to calculate the shortest path of a single source point each time,

The time complexity is about 32*10 to the power of 8,

The question takes only one second,

So the timeout rhythm.

There is an algorithm called Tarjan,

Is used to find the nearest common ancestor of two nodes,

I heard that it is the fastest algorithm that a normal person can write to find such a method,

I did not understand it.

Therefore, this question can be converted to the nearest common ancestor,

By the way, you can calculate the distance between each point and the root node.

Find this question.

The progressive time complexity of the Tarjan algorithm is the number of queries + the number of edges in the graph,

So it is 80 thousand, and will not time out.

So how do I write this algorithm.

It is probably implemented using DFS and query sets,

To speed up the access edge, I also used the chain forward star.

This data structure.

The specific point is probably like this,

Search from the root node,

Each time you search for the current vertex

Marked as added and queried sets,

Adding and querying a set means that,

This point has already been added to a subtree,

This means that a node has a recent public ancestor,

I don't know if a point is the one to be queried.

How can we find the nearest common ancestor of the two points to be queried?

Enumerate all queries,

If any of the two points is being searched

That vertex, and another vertex has already been added to a subtree,

Set the recent common ancestor of the two vertices to this vertex.

With the recent common ancestor of a point,

As for Mao, do not create.

Then search for all

No successor node is added to any subtree,

Until all nodes are added to a subtree,

This process ends.

Okay, my code is as follows:

#include<iostream>#include<cstring>using namespace std;int num_dot,num_q,num_side,cnt,box[40010],dis[40010],father[40010],vis[40010];struct node{ int e,next,w;}side[80010];struct node1{ int s,e,f;}q[210];void add(int s,int e,int w){ side[cnt].e=e; side[cnt].w=w; side[cnt].next=box[s]; box[s]=cnt++;}void init(){ int t1,t2,t3; cnt=0; scanf("%d%d",&num_dot,&num_q); num_side=num_dot-1; memset(box,-1,sizeof(box)); memset(vis,0,sizeof(vis)); vis[1]=1; dis[1]=0; for(int i=0;i<num_side;i++) { scanf("%d%d%d",&t1,&t2,&t3); add(t1,t2,t3); add(t2,t1,t3); } for(int i=0;i<num_q;i++) scanf("%d%d",&q[i].s,&q[i].e);}int find(int x){ while(x!=father[x]) x=father[x]; return x;}void dfs(int mid){ vis[mid]=1; father[mid]=mid; for(int i=0;i<num_q;i++) { if(q[i].s==mid&&vis[q[i].e]) q[i].f=find(q[i].e); else if(q[i].e==mid&&vis[q[i].s]) q[i].f=find(q[i].s); } for(int i=box[mid];i!=-1;i=side[i].next) if(!vis[side[i].e]) { dis[side[i].e]=dis[mid]+side[i].w; dfs(side[i].e); father[side[i].e]=mid; }}int main(){ int exp; scanf("%d",&exp); while(exp--) { init(); dfs(1); for(int i=0;i<num_q;i++) printf("%d\n",dis[q[i].s]+dis[q[i].e]-2*dis[q[i].f]); }}