http://acm.hdu.edu.cn/showproblem.php?pid=2874
题意:给你一个无向森林图,求任意两点距离,若不能连通,输出Not..,若连通,输出距离。查询数据量大。
思路:求距离思路和hdu2586一样,只不过这里转变为森林。这样要想判断不在一个树上,只能用并查集,把树上的点圈成一个集合,判断前再通过判断老大来确定输出方式。既然加了并查集就加了相关的操作。不过后来还是不停的MLE,数组改的特别合适也没用,结果把结构体中的from域去掉就好了,反正也没什么用。。
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 10051;
const int INF = 0x3f3f3f3f;
int head[N], head0[N], dist[N], pre[N];
int pos, pos0, n;
bool vis[N], root[N];
struct node
{
int to, w, next;
}edge[2*N];
struct node0
{
int to, w, next;
}query[2000500];
void add(int u, int v, int w)
{
edge[pos] = (struct node){v, w, head[u]};
head[u] = pos++;
edge[pos] = (struct node){u, w, head[v]};
head[v] = pos++;
}
void add0(int u, int v, int w)
{
query[pos0] = (struct node0){v, w, head0[u]};
head0[u] = pos0++;
query[pos0] = (struct node0){u, w, head0[v]};
head0[v] = pos0++;
}
void init()
{
pos = pos0 = 0;
// memset(edge, 0, sizeof(edge));
memset(root, false, sizeof(root));
// memset(query, 0, sizeof(query));
memset(dist, 0, sizeof(dist));
memset(head, -1, sizeof(head));
memset(head0, -1, sizeof(head0));
for(int i = 1; i <= n; i++)
pre[i] = i;
}
int Find(int u)
{
if(pre[u] == u) return u;
pre[u] = Find(pre[u]);
return pre[u];
}
void Union(int a, int b)
{
int x = Find(a);
int y = Find(b);
if(x != y) pre[x] = y;
}
void LCA(int u)
{
pre[u] = u;
vis[u] = true;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(!vis[v])
{
dist[v] = dist[u]+edge[i].w;
LCA(v);
pre[v] = u;
}
}
for(int i = head0[u]; i != -1; i = query[i].next)
{
int v = query[i].to;
if(vis[v])
{
query[i].w = dist[u]+dist[v]-dist[Find(v)]*2;
query[i^1].w = query[i].w;
}
}
}
int main()
{
// freopen("in.txt", "r", stdin);
int m, c, w, u, v;
while(~scanf("%d%d%d", &n, &m, &c))
{
init();
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
Union(u, v);//将输入的点合并为一个集合
}
//找根
for(int i = 1; i <= n; i++)
root[Find(i)] = true;
for(int i = 1; i <= c; i++)
{
scanf("%d%d", &u, &v);
if(Find(u) == Find(v)) add0(u, v, 0);
else add0(u, v, -1);
}
for(int i = 1; i <= n; i++)
{
if(root[i])
{
memset(vis, 0, sizeof(vis));
LCA(i);
}
}
for(int i = 0; i < pos0; i+=2)
{
if(query[i].w == -1) printf("Not connected\n");
else printf("%d\n", query[i].w);
}
}
return 0;
}