2874

/*
我实现的LCA tarjan算法(离线)
*/

// include file
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <ctime>

#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <bitset>
#include <strstream>

#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <list>
#include <functional>

using namespace std;

// typedef
typedef long long LL;
typedef unsigned long long ULL;

// 
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define FORi(a,b,c) for(int i=(a);i<(b);i+=c)
#define FORj(a,b,c) for(int j=(a);j<(b);j+=c)
#define FORk(a,b,c) for(int k=(a);k<(b);k+=c)
#define FORp(a,b,c) for(int p=(a);p<(b);p+=c)

#define FF(i,a)    for(int i=0;i<(a);i+++)
#define FFD(i,a)   for(int i=(a)-1;i>=0;i--)
#define Z(a) (a<<1)
#define Y(a) (a>>1)

const double eps = 1e-6;
const double INFf = 1e10;
const int INFi = 1000000000;
const double Pi = acos(-1.0);

template<class T> inline T sqr(T a){return a*a;}
template<class T> inline T TMAX(T x,T y)
{
	if(x>y) return x;
	return y;
}
template<class T> inline T TMIN(T x,T y)
{
	if(x<y) return x;
	return y;
}
template<class T> inline void SWAP(T &x,T &y)
{
	T t = x;
	x = y;
	y = t;
}
template<class T> inline T MMAX(T x,T y,T z)
{
	return TMAX(TMAX(x,y),z);
}


// code begin
#define MAXN 20010
#define MAXC 2000010
int N,M,C;

struct node1
{
	int next;
	int s;
	int t;
	int w;
};
node1 mem1[MAXN];
int G1[MAXN/2]; //原始图的链表
int dx1;

struct node2
{
	int next;
	int t;
	int i;
};
node2 mem2[MAXC]; 
int C2[MAXN/2]; // 查询的链表
int dx2;

int ans[MAXC/2]; //答案数组 
int CC[MAXN/2]; // 连通分量
bool used[MAXN/2]; //
int dst[MAXN/2]; 

// disjoint set
int father[MAXN/2],rank[MAXN/2];

void Init()
{
	FORi(1,N+1,1)
	{
		rank[i] = 1;
	}
}

int Find(int i)
{
	if(father[i]!=i)
		father[i] = Find(father[i]);
	return father[i];
}

// 这里合并的时候注意,a 必须是b的father
void Joint(int a,int b)
{
	a = Find(a);
	b = Find(b);
	father[b] = a;
}

void Add_edge(int a,int b,int c)
{
	mem1[dx1].t = b;
	mem1[dx1].w = c;
	mem1[dx1].next = G1[a];
	G1[a] = dx1++;
}

void Add_query(int a,int b,int i)
{
	mem2[dx2].t = b;
	mem2[dx2].i = i;
	mem2[dx2].next = C2[a];
	C2[a] = dx2++;
}

void DFS(int i,int nm)
{
	used[i] = true;
	CC[i] = nm;

	int mdx = G1[i];
	while(mdx!=-1)
	{
		int v = mem1[mdx].t;
		if(!used[v]) DFS(v,nm);

		mdx = mem1[mdx].next;
	}
}

void LCA_Tarjan(int i)
{
	if(used[i]) return;
	used[i] = true;
	father[i] = i;
	int mdx = G1[i];
	while(mdx!=-1)
	{
		int v = mem1[mdx].t;
		if(!used[v])
		{
			dst[v] = dst[i] + mem1[mdx].w;
			LCA_Tarjan(v);
			Joint(i,v);
		}

		mdx = mem1[mdx].next;
	}
	
	// 查询
	//printf("关联%d的查询\n",i);
	mdx = C2[i];
	while(mdx!=-1)
	{
		int v = mem2[mdx].t;
		
		if(used[v])
		{
			if(CC[i]==CC[v])
				ans[mem2[mdx].i] = dst[v]+dst[i]-2*dst[Find(v)];
			else
				ans[mem2[mdx].i] = -1;
		}

		mdx = mem2[mdx].next;
	}


}

int main()
{
	read;
	write;
	int a,b,c;
	while(scanf("%d %d %d",&N,&M,&C)!=-1)
	{
		memset(G1,-1,sizeof(G1));
		dx1 = 0;
		while(M--)
		{
			scanf("%d %d %d",&a,&b,&c);
			Add_edge(a,b,c);
			Add_edge(b,a,c);
		}

		memset(C2,-1,sizeof(C2));
		dx2 = 0;
		FORi(0,C,1)
		{
			scanf("%d %d",&a,&b);
			Add_query(a,b,i);
			Add_query(b,a,i);
		}

		// 先求出连通分量
		memset(CC,-1,sizeof(CC));
		memset(used,0,sizeof(used));
		int xc = 0;
		FORi(1,N+1,1)
		{
			if(!used[i])
			{
				DFS(i,xc);
				xc++;
			}
		}
		
		// 然后开始LCA
		memset(used,0,sizeof(used));
		memset(dst,0,sizeof(dst));
		memset(ans,0,sizeof(ans));
		Init();

		FORi(1,N+1,1)
		{
			if(!used[i])
			{
				LCA_Tarjan(i);
			}
		}

		// 输出查询
		FORi(0,C,1)
		{
			if(ans[i]==-1) printf("Not connected\n");
			else printf("%d\n",ans[i]);
		}

	}
	return 0;
}
posted @ 2011-03-28 15:34  AC2012  阅读(148)  评论(0编辑  收藏  举报