POJ 1470 - Closest Common Ancestors (Tarjan)

基础,关于Tajan算法解析:https://blog.csdn.net/creatorx/article/details/70739834 (?一下!)

题目地址

题目大意: Tarjan模板题,找到一对查询顶点的LCA(最近公共祖先)

         解题思路就是上面的算法解析

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N = 909;

vector<int> mp[N];     //
vector<int> ask[N];    //查询 
bool vis[N];           //标记 
bool root[N];          //找根节点 
int fa[N];             //并查集 
int res[N];            //答案 
int n;

void init()   //初始化 
{
    for(int i = 0; i <= n; i++) {
        mp[i].clear();
        ask[i].clear();
        root[i] = 1;
        vis[i] = 0;
        res[i] = 0;
        fa[i] = i;
    }
}
//并查集 
int Find(int x)
{
    return x == fa[x] ? x : (fa[x] = Find(fa[x]));
}
void merge(int x, int y)
{
    int t1, t2;
    t1 = Find(x);
    t2 = Find(y);
    if(t1 != t2) 
        fa[t2] = t1;
} 

void tarjan(int u)      // tarjan 
{
    //从根节点往下,先访问最底下的 再往回 
    for(int i = 0; i < mp[u].size(); i++) { 
        if(!vis[mp[u][i]]) {      //未访问过的点 
            int v = mp[u][i];   
            tarjan(v);
            merge(u,v);              //合并
            vis[mp[u][i]] = true;    //标记已访问 
        }
    }
    for(int i = 0; i < ask[u].size(); i++) {
        if(vis[ask[u][i]]) {         //如果已经访问 
            int fu = Find(ask[u][i]); 
            res[fu] ++;               
        }
    }
}
int main()
{
    while(~scanf("%d",&n)) {
        int x, y, t;
        init();
        for(int i = 0; i < n; i++) {
            scanf("%d:(%d)",&x,&y);
            while(y--) {
                scanf(" %d",&t);
                mp[x].push_back(t);
                root[t] = false;
            }
        }
        scanf("%d",&t);
        while(t--) {
            scanf(" (%d%d)",&x,&y);
            ask[x].push_back(y);
            ask[y].push_back(x);
        }
        for(int i = 1; i <= n; i++) {
            if(root[i]) {
            //    cout << "root " << i << endl;
                tarjan(i);
                break;
            }
        }
        for(int i = 1; i <= n; i++) 
            if(res[i]) 
                printf("%d:%d\n",i,res[i]);
    }
    return 0;
}
/*
9
4:(3) 7 9 8
7:(1) 3
9:(2) 2 6
8:(2) 5 1
3:(0)
2:(0)
6:(0)
5:(0)
1:(0)
6
(2 6) (1 8) (5 8) (2 4) (3 7) (6 1)
*/
View Code

 

图论使我晕倒...   枯了  

转载于:https://www.cnblogs.com/JiaaaaKe/p/11314541.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值