我就想存个板子而已
倍增法:
#include<bits/stdc++.h> using namespace std; const int maxn=1e5; struct Edge { int to; int d; int next; }edge[maxn*2]; int head [maxn],tot,in[maxn]; void addedge(int u,int v,int w) { edge[tot].to=v; edge[tot].next=head[u]; edge[tot].d=w; head[u]=tot++; } void init () { tot=0; memset(in,0,sizeof(in)); memset(head,-1,sizeof(head)); } int fa[maxn][30]; int deg[maxn],d[maxn]; void BFS(int root) { queue <int > que; deg[root]=d[root]=0; fa[root][0]=root; que.push(root); while(!que.empty()) { int tmp=que.front(); que.pop(); for(int i=1;i<30;i++) fa[tmp][i]=fa[fa[tmp][i-1]][i-1]; for(int i=head[tmp];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==fa[tmp][0])continue; deg[v]=deg[tmp]+1; d[v]=d[tmp]+edge[i].d; fa[v][0]=tmp; que.push(v); } } } int LCA (int u,int v) { if(deg[u]>deg[v])swap(u,v); int hu=deg[u],hv=deg[v]; int tu=u,tv=v; for(int det=hv-hu,i=0;det;det>>=1,i++) { if(det&1) tv=fa[tv][i]; } if(tu==tv)return tu; for(int i=30-1;i>=0;i--) { if(fa[tu][v]==fa[tv][i])continue; tu=fa[tu][i]; tv=fa[tv][i]; } return fa[tu][0]; } int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); init(); for(int i=0;i<n-1;i++) { int u,v,val; scanf("%d%d%d",&u,&v,&val); addedge(u,v,val); addedge(v,u,val); in[v]=1; } int tt; for(int i=1;i<=n;i++) { if(!in[i]){tt=i;break;} } BFS(tt); while(m--) { int u,v; scanf("%d%d",&u,&v); printf("%d\n",d[u]+d[v]-2*d[LCA(u,v)]); } } }
Tarjan:
#include<bits/stdc++.h> using namespace std; const int N=40000+100; int head[N]; int vis[N]; int parent[N]; int ans[N]; int cnt; vector<int>q[N]; vector<int>Q[N]; int dis[N]; int n; int ancestor[N]; struct node{ int to,next,w; }edge[2*N+10]; void init(){ cnt=0; memset(ans,0,sizeof(ans)); memset(dis,0,sizeof(dis)); memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); for(int i=0;i<=n;i++){ parent[i]=i; Q[i].clear(); q[i].clear(); } } void add(int u,int v,int w){ edge[cnt].to=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; } int find(int x){ int r=x; while(r!=parent[x])r=parent[r]; int i=x; int j; while(parent[i]!=r){ j=parent[i]; parent[i]=r; i=j; } return r; } void Union(int x,int y){ x=find(x); y=find(y); if(x!=y)parent[y]=x; } void Tarjan(int x,int w){ vis[x]=1; dis[x]=w; //cout<<dis[x]<<endl; for(int i=head[x];i!=-1;i=edge[i].next){ int v=edge[i].to; if(vis[v])continue; Tarjan(v,w+edge[i].w); Union(x,v); ancestor[find(x)]=x; } for(int i=0;i<q[x].size();i++){ int u=q[x][i]; if(vis[u]){ int t=ancestor[find(u)]; ans[Q[x][i]]=dis[x]+dis[u]-dis[t]*2; } } } int main(){ int m; int t; scanf("%d",&t); while(t--){ init(); scanf("%d%d",&n,&m); int u,v,w; for(int i=0;i<n-1;i++){ scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); q[u].push_back(v); q[v].push_back(u); Q[u].push_back(i); Q[v].push_back(i); } Tarjan(1,0); // for(int i=1;i<=n;i++)cout<<dis[i]<<" "; //cout<<endl; for(int i=0;i<m;i++){ // cout<<4<<endl; cout<<ans[i]<<endl; } } }