hdu 2874 Connections between cities

离线算法求解最近公共祖先,第一次见卡内存这么紧的题= =。

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值