Online JudgeProblem SetAuthorsOnline ContestsUser
Web Board
Home Page
F.A.Qs
Statistical Charts
Problems
Submit Problem
Online Status
Prob.ID:
Register
Update your info
Authors ranklist
Current Contest
Past Contests
Scheduled Contests
Award Contest
User ID:
Password:
  Register

我不是男人!附上小弟使用LCA的TLE算法.

Posted by donkeyinacm at 2010-02-24 21:13:35 on Problem 1741
//Tarjan算法这是一个离线算法复杂度是O(N+Q),我在Q上无法优化,为N^2,所以超时了.路过的请帮我想想有没有办法.



#include <cstdio>
#include <cstdlib>
#include <vector>

using namespace std;

#define MAXN  10005
#define MAXE 100005
struct edge
{
	__int32 adj,dis,num;
};
vector<edge>  Tree[MAXN];
__int32  set[MAXN], ancestor[MAXN], rank[MAXN], num, dis[MAXN];
bool visite[MAXN],edgeused[MAXE];
__int32  n, k,ecount;

bool input()
{    
	scanf("%I32d%I32d",&n,&k);
	if(n+k==0) return false;//节点个数

	for( __int32 i= 1; i<= n; ++i )
		Tree[i].clear();
    ecount=0;
	memset( set, 0, sizeof(set) );
	memset( dis, 0, sizeof(dis) );
	memset( ancestor, 0, sizeof(ancestor) );
	memset( rank, 0, sizeof(rank) );
	//memset( root, 0, sizeof(root) );
	num=0;
	memset( visite,false, sizeof(visite) );
    memset( edgeused, 0, sizeof(edgeused) );
	__int32 u, v, d;

	for( __int32 i= 1; i<=n-1; ++i )
	{
		scanf("%I32d%I32d%I32d",&u,&v,&d);
		edge e1={v,d,ecount};
		Tree[u].push_back(e1);
		edge e2={u,d,ecount};
		Tree[v].push_back(e2);
		ecount++;
		//root[v]++;//对每个出现的子节点进行标记,最后没有标记那个是根节点
	}
	return true;
}

void make_set( __int32 u )
{
	set[u]= u;
}

__int32 find_set( __int32 u )
{
	while( u!= set[u] ) u= set[u];

	return u;
}

void union_set( __int32 u, __int32 v )
{
	__int32 x= find_set(u), y= find_set(v);

	if( rank[x]> rank[y] )
		set[y]= x;
	else
	{
		set[x]= y;

		if( rank[x]== rank[y] ) rank[y]++;//rank表示树的深度,浅的接到深的树上.只当两棵树深度相同时的,才会让原本的树发生深度变更.
	}
}

void lca( __int32 u ,__int32 high)
{
	
	dis[u]=high;
	make_set(u);
	ancestor[u]= u;

	for( size_t i= 0; i< Tree[u].size(); ++i )
	if(!edgeused[Tree[u][i].num])
	{
		edgeused[Tree[u][i].num]=true;
		lca( Tree[u][i].adj,high+  Tree[u][i].dis);

		union_set( u, Tree[u][i].adj );//合并后,u不再是以前的u,所以要执行 ancestor[ find_set(u) ]= u;
		ancestor[ find_set(u) ]= u;
	}

	__int32 v;
	visite[u]= true;
	for(v=1;v<=n;++v )//query[u][i]=v,要查询的是(u,v)的最近祖先节点
		if(v!=u)
		if( visite[ v ] ) 
		{
			__int32 p=ancestor[ find_set( v ) ] ;
			__int32 d=dis[u]-dis[p]+dis[v]-dis[p];
		//	printf("u:%d v:%d p:%d d:%d\n",u,v,p,d);
			if(d<=k)
				num++;
		}
}

int main()
{
	freopen("c:/aaa.txt","r",stdin);
	while( input() )
	{
		for( __int32 i= 1; i<= n; ++i )
		//	if( root[i]== 0 )
			{
				lca( 1,0);
				break;
			}
			printf("%I32d\n",num );
	}

	return 0;
}


Followed by:

Post your reply here:
User ID:
Password:
Title:

Content:

Home Page   Go Back  To top


All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator