您的位置:首页 > 其它

hdu 2874 lca-tarjan离线算法(模板)

2015-08-09 20:44 330 查看
题意:

给n个点,m条边带权值的森林,然后q(10^6)次询问,询问每个点之间的最短距离,若两点不属于同一个联通块,则输出not ...

解析:

新学了一种lca-tarjan的模板,看起来稳多了。

这题是遍历所有的点,把森林中的也变成lca。

然后记录答案,最后如果答案被修改过,就输出,如果为-1,则点没有被连到。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <climits>
#include <cassert>
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define LL long long
#define lson lo, mi, rt << 1
#define rson mi + 1, hi, rt << 1 | 1

using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = acos(-1.0);
const double ee = exp(1.0);

const int maxn = 10000 + 10;
const int maxm = 20000 + 10;
const int maxq = 2000000 + 10;

int n, m, q;
int dis[maxn], vis[maxn], ancestor[maxn];
int ans[maxq >> 1];

struct Edge
{
int to, next;
int len;
} edge[maxm];

int edgeNum;
int edgeHead[maxn];
void addEdge(int fr, int to, int len)
{
edge[edgeNum].to = to;
edge[edgeNum].len = len;
edge[edgeNum].next = edgeHead[fr];
edgeHead[fr] = edgeNum++;

edge[edgeNum].to = fr;
edge[edgeNum].len = len;
edge[edgeNum].next = edgeHead[to];
edgeHead[to] = edgeNum++;
}

struct Query
{
int to, next;
int id;
} query[maxq];

int queryNum;
int queryHead[maxn];
void addQuery(int fr, int to, int id)
{
query[queryNum].to = to;
query[queryNum].id = id;
query[queryNum].next = queryHead[fr];
queryHead[fr] = queryNum++;

query[queryNum].to = fr;
query[queryNum].id = id;
query[queryNum].next = queryHead[to];
queryHead[to] = queryNum++;
}

int Find(int x)
{
if (ancestor[x] == x)
return x;
return ancestor[x] = Find(ancestor[x]);
}

void lca(int u, int dep, int rt)
{
ancestor[u] = u;
vis[u] = rt;
dis[u] = dep;

for (int i = edgeHead[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if (vis[v] == -1)
{
lca(v, dep + edge[i].len, rt);
ancestor[v] = u;
}
}
for (int i = queryHead[u]; i != -1; i = query[i].next)
{
int v = query[i].to;
if (vis[v] == rt)
{
//ans[query[i].id] = ancestor[Find(v)]
ans[query[i].id] = dis[v] + dis[u] - 2 * dis[Find(v)];
}
}
}

void init()
{
edgeNum = 0;
queryNum = 0;
memset(edgeHead, -1, sizeof(edgeHead));
memset(queryHead, -1, sizeof(queryHead));
memset(vis, -1, sizeof(vis));
memset(ans, -1, sizeof(ans));
}

int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (~scanf("%d%d%d", &n, &m, &q))
{
init();
while (m--)
{
int fr, to, len;
scanf("%d%d%d", &fr, &to, &len);
addEdge(fr, to, len);
}
for (int i = 0; i < q; i++)
{
int fr, to;
scanf("%d%d", &fr, &to);
ans[i] = -1;
addQuery(fr, to, i);
}
for (int i = 1; i <= n; i++)
{
if (vis[i] == -1)
{
lca(i, 0, i);
}
}
for (int i = 0; i < q; i++)
{
if (ans[i] == -1)
{
puts("Not connected");
}
else
{
printf("%d\n", ans[i]);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: