HDU2874 Connections between cities LCA+DFS或并查集

Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=2874


【前言】


这两天在做LCA的问题。

昨天做了一道模板题,今天再做一道。

但是一开始就被C++WA而G++AC困惑着。

最后的最后,好久好久以后,终于得到了一个结论。


【思路】


题意所给是一个森林,那么加多一个虚根节点,使其成为一棵树。

如果两个节点的LCA是虚根节点,则表示不可连通。

否则距离等于每个节点到虚根节点的距离之和减去两倍LCA到虚根节点的距离。

可以使用并查集,但是貌似跟直接深搜的时间差不多。不过可能会好一点。


【代码】


#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

const int maxn = 10000;

struct node
{
	int length;
	int index;
	int next;
	node(int idx = 0, int len = 0)
	{
		index = idx;
		length = len;
	}
}edge[maxn<<1+5];
int head[maxn+5];
int ect;

void addedge(int from, int to, int len)
{
	edge[ect].index = to;
	edge[ect].length = len;
	edge[ect].next = head[from];
	head[from] = ect;
	ect++;
}

int F[maxn<<1];
int B[maxn<<1];
int Pos[maxn+5];
int D[maxn+5];
int has[maxn+5];

void dfs(int rt, int level, int len, int &ct)
{
	ct++;
	has[rt] = 1;
	F[ct] = rt;
	B[ct] = level;
	D[rt] = len;
	Pos[rt] = ct;
	int i;
	for (i=head[rt]; i+1!=0; i=edge[i].next)
	{
		if (has[edge[i].index]==0)
		{
			dfs(edge[i].index, level+1, len+edge[i].length, ct);
			ct++;
			F[ct] = rt;
			B[ct] = level;
		}
	}
}

int dpmin[maxn<<1+10][20];

void ST(int n)
{  
    int i,j;  
    for (i=1; i<=n; i++)
	{
		dpmin[i][0] = i;
	}
    int m = (int)floor(log((double)n)/log(2.0));   
    for (j=1; j<=m; j++)  
    {  
        for (i=1; i<=n; i++)  
        {   
            dpmin[i][j] = dpmin[i][j-1];  
            if (i+(1<<(j-1))<=n)  
            {  
				if (B[dpmin[i][j-1]]<B[dpmin[i+(1<<(j-1))][j-1]])
					dpmin[i][j] = dpmin[i][j-1];
				else
					dpmin[i][j] = dpmin[i+(1<<(j-1))][j-1];
            }  
        }  
    }  
}  

int st_getmin(int l, int r)
{  
    int k = floor(log((double)(r-l+1))/log(2.0));  
    if (B[dpmin[l][k]]<B[dpmin[r-(1<<k)+1][k]])
		return dpmin[l][k];
	else 
		return dpmin[r-(1<<k)+1][k];  
}  

int getmin(int a, int b)
{
	a = Pos[a], b = Pos[b];
	if (a>b) swap(a, b);
	return F[st_getmin(a, b)];
}

void solve(int rt)
{
	int ct = 0;
	memset(has, 0, sizeof(has));
	dfs(rt, 0, 0, ct);
	ST(ct);
}

int father[maxn+5]; 
  
void init(int n) 
{  
    int i;  
    for (i=0; i<=n; i++)  
    {  
        father[i] = i;  
    }  
}  
  
inline int getroot(int x) 
{  
    int r = x;  
    while(father[r]!=r)  
    {  
        r = father[r];  
    }  
    while(father[x]!=r)  
    {  
        father[x] = r;  
        x = father[x];  
    }  
    return r;  
}   
  
inline void join(int s, int x)
{  
    int a = getroot(s);  
    int b = getroot(x);  
    if (a!=b)  
    {  
        father[a] = b;  
    }  
}  

int main()
{
	int n, m, c;
	int x, y, z;
	int i;
	while(scanf("%d %d %d", &n, &m, &c)!=EOF)
	{
		for (i=1; i<=n+1; i++) head[i] = -1;
		ect = 0;
         //以下所有注释部分就是使用并查集
	//	init(n+1);
		for (i=0; i<m; i++)
		{
			scanf("%d %d %d", &x, &y, &z);
			addedge(x, y, z);
			addedge(y, x, z);
	//		join(x, y);
		}
		
		memset(has, 0, sizeof(has));//这部分是使用深搜
		for (i=1; i<=n; i++)
		{
			if (has[i]==0)
			{
				addedge(n+1, i, 0);
				z = 0;//如果不赋值为0,g++AC,c++WA。
				dfs(i, 0, 0, z);
			}
		}
		/*
		for (i=1; i<=n; i++)
			if (father[i]==i)
				addedge(n+1, i, 0);*/
		solve(n+1);
		while(c--)
		{
			scanf("%d %d", &x, &y);
			int rt = getmin(x, y);
			if (rt==n+1)
				printf("Not connected\n");
			else
				printf("%d\n", D[x]+D[y]-2*D[rt]);
		}
	}
	return 0;
}


你可能感兴趣的:(HDU2874 Connections between cities LCA+DFS或并查集)