题目链接【https://vjudge.net/problem/HDU-2874】
题意: 输入一个森林,总节点不超过N(N<10000),由C次询问(C<1000000),每次询问两个点,如果来联通输出,两点之间的距离,如果不来联通,输出“Not connected”;
思路:首先判断u,v两个点在不在同一个树上,用并查集来做,如果在,就求两者的LCA,输入距离dis[u->v]=dis[u]+dis[v]-2*dis[LCA(u,v)]。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = ;
int N, M, C;
struct node
{
int id, next, len;
} E[maxn << ];
int head[maxn << ], num;
void initlist()
{
memset(head, -, sizeof(head));
num = ;
}
void adde(int u, int v, int len)
{
E[num].id = u;
E[num].len = len;
E[num].next = head[v];
head[v] = num++;
}
//----------------------------------------邻接表
int fa[maxn<<];
void initfa()
{
for(int i = ; i <= N; i++)
fa[i] = i;
}
int Find(int id)
{
if(id == fa[id]) return id;
else return fa[id] = Find(fa[id]);
}
void addu(int u, int v)
{
int x = Find(u);
int y = Find(v);
if(x != y) fa[x] = y;
}
//----------------------------------------并查集
int p[][maxn], dep[maxn], dis[maxn], vis[maxn];
void DFS(int u, int FA)
{
vis[u] = ;
for(int l = head[u]; l != -; l = E[l].next)
{
int id = E[l].id;
if(id == FA||vis[id]) continue;
dep[id] = dep[u] + ;
dis[id] = dis[u] + E[l].len;
p[][id] = u;
DFS(id, u);
}
}
void initlca()
{
memset(p, -, sizeof(p));
memset(dep,,sizeof(dep));
memset(dis, , sizeof(dis));
memset(vis, , sizeof(vis));
for(int i = ; i <= N; i++)
{
if(!vis[i])
DFS(i, -);
}
for(int k = ; k + <= ; k++)
for(int u = ; u <= N; u++)
{
if(p[k][u] < ) p[k + ][u] = -;
else
p[k + ][u] = p[k][p[k][u]];
}
}
int LCA(int u, int v)
{
if(dep[u] > dep[v]) swap(u, v);
for(int k = ; k <= ; k++)
{
if((dep[v] - dep[u]) >> k & )
v = p[k][v];
}
if(u == v) return u;
for(int k = ; k >= ; k--)
{
if(p[k][u] != p[k][v])
{
u = p[k][u];
v = p[k][v];
}
}
return p[][u];
}
//----------------------------------------LCA
int main ()
{
while(~scanf("%d%d%d", &N, &M, &C))
{
initlist();
initfa();
int u, v, ds;
for(int i = ; i <= M; i++)
{
scanf("%d%d%d", &u, &v, &ds);
adde(u, v, ds);
adde(v, u, ds);
addu(u, v);
}
initlca();
for(int i=;i<=C;i++)
{
scanf("%d%d",&u,&v);
int x=Find(u);
int y=Find(v);
if(x==y)
{
printf("%d\n",dis[u]+dis[v]-*dis[LCA(u,v)]);
}
else
printf("Not connected\n");
}
}
return ;
}
//#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = ;
//---------------------------------//邻接表
struct node
{
int to, len, next;
} E[MAXN * ];
int p[MAXN * ], tot;
void init()
{
memset(p, -, sizeof(p));
tot = ;
}
void add(int u, int v, int len)
{
E[tot].to = v;
E[tot].len = len;
E[tot].next = p[u];
p[u] = tot++;
}
//---------------------------------//并查集
int fa[MAXN * ];
void init2(int n)
{
for(int i = ; i <= n; i++)
fa[i] = i;
}
int Find(int x)
{
if(x == fa[x])
return fa[x];
else
return fa[x] = Find(fa[x]);
}
void join (int i, int j)
{
int x = Find(i);
int y = Find(j);
if(x != y) fa[y] = x;
}
//----------------------------------//LAC
int ver[MAXN * ], vis[MAXN], fst[MAXN], R[MAXN * ];
int dis[MAXN], KT[MAXN * ], dp[MAXN * ][];
void init3()
{
memset(vis, , sizeof(vis));
tot = ;
}
void DFS(int u, int dep, int len)
{
vis[u] = ;
ver[++tot] = u;
R[tot] = dep;
fst[u] = tot;
dis[u] = len;
for(int k = p[u]; k != -; k = E[k].next)
{
int v = E[k].to;
if(vis[v]) continue;
DFS(v, dep + , len + E[k].len);
ver[++tot] = u;
R[tot] = dep;
}
}
void ST(int n)
{
KT[] = ;
for(int i = ; i <= n; i++)
KT[i] = KT[i / ] + ;
for(int i = ; i <= n; i++)
dp[i][] = i;
for(int j = ; j <= KT[n]; j++)
for(int i = ; i + ( << j) - <= n; i++)
{
int x = dp[i][j - ];
int y = dp[i + ( << (j - ))][j - ];
dp[i][j] = R[x] < R[y] ? x : y;
}
}
int RMQ(int l, int r)
{
int k = KT[r - l + ];
int x = dp[l][k];
int y = dp[r - ( << k) + ][k];
return R[x] < R[y] ? x : y;
}
int LCA(int u, int v)
{
int l = fst[u], r = fst[v];
if(l > r) swap(l, r);
int t = RMQ(l, r);
return ver[t];
}
//-------------------------------------//主函数
int N, M, C;
int main ()
{
while(~scanf("%d%d%d", &N, &M, &C))
{
init();//
init2(N);
int u, v, len;
for(int i = ; i <= M; i++)
{
scanf("%d%d%d", &u, &v, &len);
add(u, v, len);
add(v, u, len);
join(u, v);
}
init3();
for(int i = ; i <= N; i++)
{
if(vis[i]) continue;
DFS(i, , );
}
ST( * N - );
for(int i = ; i <= C; i++)
{
scanf("%d%d", &u, &v);
int x = Find(u);
int y = Find(v);
if(x != y)
{
printf("Not connected\n");
continue;
}
int lca = LCA(u, v);
printf("%d\n", dis[u] + dis[v] - * dis[lca]);
}
}
return ;
}