题意:求两点间的距离,可能不连通
思路:连不连通,用并查集解决。不连通,我直接给每个连通集建了一个树状数组,不用想T了。其实只要建个虚根,把每个连通集的一个点连过去就行了,真是奇妙。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<list>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define lson(x) 2*x
#define rson(x) 2*x+1
const int maxn = 20005;
struct Edge
{
int to,cost,id,next;
}edge[maxn];
int head[maxn],tot;
int rmq_n; // rmq_n -> 线段树的点,2 * n - 1
int vs[maxn*2],depth[maxn*2],id[maxn];
int tree[maxn*4],bit_n;
int root;
int pre[maxn];
struct data
{
int l,r,num,dep; //num -> 下标,dep -> depth最小值
}node[maxn*4];
void init(int x)
{
memset(head,-1,sizeof head);
tot = 0;
for(int i = 0; i <= x; i++)
pre[i] = i;
}
void addedge(int a,int b,int c)
{
edge[tot].to = b;
edge[tot].cost = c;
edge[tot].next = head[a];
head[a] = tot++;
}
int lowbit(int k)
{
return k & -k;
}
void add(int cnt,int val)
{
while(cnt <= bit_n) // n -> num of point
{
tree[cnt] += val;
cnt += lowbit(cnt);
}
}
int fid(int cnt) // 1 ~ k sum
{
int sum = 0;
while(cnt)
{
sum += tree[cnt];
cnt -= lowbit(cnt);
}
return sum;
}
void pushup(int cnt)
{
node[cnt].dep = min(node[lson(cnt)].dep,node[rson(cnt)].dep);
if(node[lson(cnt)].dep < node[rson(cnt)].dep)
node[cnt].num = node[lson(cnt)].num;
else
node[cnt].num = node[rson(cnt)].num;
}
void build(int x,int y, int cnt)
{
node[cnt].l = x;
node[cnt].r = y;
if(x == y)
{
node[cnt].num = vs[x];
node[cnt].dep = depth[x];
return;
}
int mid = (x+y) / 2;
build(x,mid,lson(cnt));
build(mid+1,y,rson(cnt));
pushup(cnt);
}
pii query(int x,int y,int cnt)
{
pii a,b;
a.second = 0x3f3f3f3f;
b.second = 0x3f3f3f3f;
if(x == node[cnt].l && y == node[cnt].r)
{
return make_pair(node[cnt].num,node[cnt].dep);
}
int fa = 2*cnt;
if(x <= node[fa].r)
{
if(y <= node[fa].r)
a = query(x,y,fa);
else
a = query(x,node[fa].r,fa);
}
fa++;
if(y >= node[fa].l)
{
if(x >= node[fa].l)
b = query(x,y,fa);
else
b = query(node[fa].l,y,fa);
}
if(a.second < b.second)
return a;
else
return b;
}
void dfs(int v,int p,int d,int &k)
{
id[v] = k;
vs[k] = v;
depth[k++] = d;
for(int i = head[v]; i != -1; i = edge[i].next)
{
Edge &e = edge[i];
if(e.to != p)
{
add(k,e.cost);
dfs(e.to,v,d+1,k);
vs[k] = v;
depth[k++] = d;
add(k,-e.cost);
}
}
}
void yu(int x)
{
rmq_n = 2*x-1;
root = 0;
bit_n = 2 *(x-1); //走过几条边,算边权和
for(int i = 0; i <= bit_n; i++)
tree[i] = 0;
int k = 1;
dfs(root,-1,0,k);
build(1,rmq_n,1);
}
int fa(int x)
{
if(pre[x] == x)
return x;
else
return pre[x] = fa(pre[x]);
}
void he(int x,int y)
{
int nx = fa(x);
int ny = fa(y);
if(nx != ny)
pre[nx] = ny;
}
int main(void)
{
int n,m,q;
while(scanf("%d%d%d",&n,&m,&q)!=EOF)
{
init(n);
while(m--)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
he(a,b);
addedge(a,b,c);
addedge(b,a,c);
}
for(int i = 1; i <= n; i++)
{
if(fa(i) == i)
{
addedge(0,i,0);
addedge(i,0,0);
}
}
yu(n+1);
for(int i = 1; i <= q; i++)
{
int a,b;
scanf("%d%d",&a,&b);
int x = fa(a);
int y = fa(b);
if(x != y)
printf("Not connected\n");
else
{
pii f = query(min(id[a],id[b]),max(id[a],id[b]),1);
int lca = f.first;
int ans = fid(id[a]) + fid(id[b]) - 2 * fid(id[lca]);
printf("%d\n",ans);
}
}
}
return 0;
}