离线算法求解最近公共祖先,第一次见卡内存这么紧的题= =。
#pragma comment (linker, "/STACK:1024000000, 1024000000")
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10010;
const int MAX = 1000010;
int n, m, c;
int tot, head[N];
int tot_q, head_q[N];
int dis[N], vis[N], father[N], ans[MAX];
struct edge{
int v, w, next;
}node[N << 1];
void addedge(int u, int v, int w){//存树
node[tot].v = v;
node[tot].w = w;
node[tot].next = head[u];
head[u] = tot++;
}
struct query{
int v, index,next;
}node_q[MAX << 1];
void addedge_q(int u, int v, int index){//存询问
node_q[tot_q].v = v;
node_q[tot_q].index = index;
node_q[tot_q].next = head_q[u];
head_q[u] = tot_q++;
}
void init(){
tot = tot_q = 0;
memset(head, -1, sizeof(head));
memset(head_q, -1, sizeof(head_q));
}
int find(int x){
if(x != father[x])
father[x] = find(father[x]);
return father[x];
}
void lca(int u, int deep, int fa){
vis[u] = fa;
dis[u] = deep;
father[u] = u;//深搜之前的操作
for(int i=head[u]; i!=-1; i=node[i].next){
int v = node[i].v;
if(vis[v] != -1) continue;
lca(v, deep + node[i].w, fa);//递归
father[v] = u;//回溯的时候更新结点的父亲
}
for(int i=head_q[u]; i!=-1; i=node_q[i].next){
int v = node_q[i].v;
if(vis[v] != fa) continue;
ans[node_q[i].index] = dis[u] + dis[v] - 2 * dis[find(v)];
}
}
int main(){
while(scanf("%d%d%d",&n,&m,&c) == 3){
init();
for(int i=0; i<m; i++){
int u, v, w;
scanf("%d%d%d",&u,&v,&w);
addedge(u, v, w);
addedge(v, u, w);
}
for(int i=0; i<c; i++){
int u, v;
scanf("%d%d",&u,&v);
addedge_q(u, v, i);
addedge_q(v, u, i);
ans[i] = -1;
}
memset(vis, -1, sizeof(vis));
for(int i=1; i<=n; i++)//这样是因为不连通
if(vis[i] == -1)
lca(i, 0, i);
for(int i=0; i<c; i++)
if(ans[i] == -1) puts("Not connected");
else printf("%d\n",ans[i]);
}
return 0;
}