hdu2586[lca離線tarjon算法][遞歸與非遞歸]


hdu2586[lca]

tarjon 是離線的算法,  在線的話會有倍增法和rmq,其實這2個方法有一曲同工之妙

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;
const int maxn=100000+123;

#define forg(p,x) for(p=x; ~p; p=edge[p].next)

struct Edge{
    int v, w, next;
}edge[maxn*2];
int head[maxn], cnt;
// for graph
void addedge(int u, int v, int w)
{
    edge[cnt].v=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}

int fath[maxn], used[maxn];
// for dis-union

struct query{
    int a, b, lca;
}list[maxn];
// for


struct Ans{
    int v, idx;
};
vector<Ans> ques[maxn];
// for every query

int find (int x)
{
    return fath[x]=(x==fath[x]? x: find(fath[x]));
}

inline void merge (int x, int y)
{
    fath[find(y)]=find(x);
}

int dis[maxn];
void dfs(int u, int r)
{
    for (int p=head[u]; ~p; p=edge[p].next)
    {
        const int &v=edge[p].v;
        if(r==v)continue;
        dis[v]=dis[u]+edge[p].w;
        dfs(v, u);
    }
}

void LCA(int u, int r)
{
    int p;
    fath[u]=u;
    //printf("u===%d\n", u);
    forg(p, head[u])
    {
        const int &v=edge[p].v;
        if(v==r)continue;
        LCA(v, u);
        merge(u, v);///u, v 順序固定,必須將子合併到父,按秩合併不是和重要
    }
    //printf("%d  %d\n", anc[u], fath[u]);
    for(int i=0; i<ques[u].size(); ++i)
    {
        const int &v=ques[u][i].v;
        if(~fath[v])
            list[ques[u][i].idx].lca=fath[find(v)];
    }
}

bool isroot[maxn];
void init(int x)
{
    for (int i=0; i<x; ++i)
    {
        ques[i].clear();
        fath[i]=i;
    }
    memset (head, -1, sizeof(head));
    cnt=0;
}


int main ()
{
    char op[10];
    int n, m;
    int cas; scanf("%d", &cas);
    while (cas--)
    {
        scanf("%d%d", &n, &m);
        init(n);
        for (int i=1; i<n; ++i)
        {
            int a, b, c; scanf("%d %d %d", &a, &b, &c, op);
            a--; b--;
            addedge(a, b, c);
            addedge(b, a, c);
        }
        for (int i=0; i<m; ++i)
        {
            int a, b; scanf("%d%d", &a, &b);
            a--; b--;
            list[i].a=a; list[i].b=b;
            Ans tmp; tmp.v=b; tmp.idx=i;
            ques[a].push_back(tmp);
            tmp.v=a;
            ques[b].push_back(tmp);
        }
        //puts("!");
        dfs(0, -1);
        LCA(0, -1);
        for (int i=0; i<m; ++i)
        {
            printf("%d\n", dis[list[i].a]+dis[list[i].b]-2*dis[list[i].lca]);
        }
    }
    return 0;
}

zoj 2615 cells 非遞歸的tarjon.

yes no打錯了。 wa了2次纔看出來

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <vector>
#define copy(a, b) memcpy(a, b, sizeof(a)); 
#define clean(a, x) memset (a, x, sizeof(a));
using namespace std;

const int maxn=300000+123;
int anc[20000000+123]; 
#define vex edge[p].v
struct Edge{int v, next;}edge[2*maxn];
int head[maxn], cnt;
void addedge(int u, int v){
	//printf("%d %d\n", u, v);
edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++;
}

int fath[maxn], used[maxn];
struct Ans{
	int v, idx;
};

vector< Ans > ques[maxn];

int find (int x)  
{  
    return fath[x]=(x==fath[x]? x: find(fath[x]));  
}  
  
inline void merge (int x, int y)  
{  
    fath[find(y)]=find(x);  
}  

stack<int> S;
int cur[maxn], pre[maxn];
int res[1000000+123];
void LCA(int rt)
{
	S.push(0);
	fath[0]=0;
	pre[0]=-1;
	copy(cur, head);
	while (!S.empty())
	{
		bool flag=false;
		int u=S.top();
		///printf("%d\n", u);
		for (int p=cur[u]; ~p; p=edge[p].next)
		{
			S.push(vex);
			fath[vex]=vex;
			pre[vex]=u;
			flag=true;
			cur[u]=edge[p].next;
			break;
		}
		if(flag)continue;
		///printf("%d is over\n", u);
		S.pop();
		for (int i=0; i<ques[u].size(); ++i)
		{
			const Ans &a=ques[u][i];
			if(~fath[a.v])
				res[a.idx]=fath[find(a.v)];
		///printf("anc==%d %d\n", res[a.idx], a.idx);
		}
		if(~pre[u])
		{
			merge(pre[u], u);
		}
	}
}

void init()
{
	clean(head, -1); cnt=0;
}
int qa[1000000+123];
int main()
{
	int cas; scanf("%d", &cas);
	for (int I=1; I<=cas; ++I)
	{
		int n; scanf("%d", &n);
		int num=0;
		init();
		for (int i=0; i<n; ++i)
		{
			ques[i].clear();
			fath[i]=i;
			int sc; scanf("%d", &sc);
			for (int j=0; j<sc; ++j)
			{
				num++;
//				addedge(i, num);
				if(num<n)addedge(i, num);
				else anc[num-n]=i;
			}
		}
		//printf("num==%d\n", num);
		int m; scanf("%d", &m);
		for (int i=0; i<m; ++i)
		{
			int a, b; scanf("%d%d", &a, &b);
			if(a!=b)qa[i]=a;
			else qa[i]=-1;
			if(a>=n)a=anc[a-n];
			if(b>=n)b=anc[b-n];
			Ans tmp; tmp.v=b; tmp.idx=i;
			ques[a].push_back(tmp);
			tmp.v=a;
			ques[b].push_back(tmp);
		}
		LCA(0);
		if(I!=1)printf("\n");
		printf("Case %d:\n", I);
		for (int i=0; i<m; ++i)
		{
			///printf("%d %d ", qa[i], res[i]);
			if(qa[i]==res[i])puts("Yes");
			else puts("No");
		}
	}
	return 0;
} 
/*
2
6
3 2 1 1 1 2
10
0 1
2 4
3 5
1 8
6 9
8 9
5 5
5 9
0 9
9 10
5
2 0 3 0 1
4
2 6
1 6
2 3
3 5

*/



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章