poj-1470

7 篇文章 0 订阅
7 篇文章 0 订阅
// 3452K   719MS   C++
#include <cstdio>
#include <cstring>

const int MAX = 910;

struct TreeNode {
    int NextBroId;
    int parentId;
};

typedef struct TreeNode TreeNode;

int LCACounter[MAX];

int querys[MAX][MAX];

int childListHead[MAX];

int UF_Ancestor[MAX];

int queryNum;
int caseNum;
int nodeNum;

TreeNode tree[MAX];

int ancestor[MAX];

char fullyVisited[MAX];

int querySolvedNum;

void insertIntoChildList(int parentId, int childId) {
    tree[childId].parentId = parentId;
    int prevChildListHeadId = childListHead[parentId];
    tree[childId].NextBroId = prevChildListHeadId;
    childListHead[parentId] = childId;
}

inline int UF_find(int nodeId) {
    // printf("UF_find %d\n", nodeId);
    int parentNodeUFId = nodeId;

    if (UF_Ancestor[parentNodeUFId] != parentNodeUFId) {
        UF_Ancestor[nodeId] = UF_find(UF_Ancestor[parentNodeUFId]);
        return UF_Ancestor[nodeId];
    } else {
        return parentNodeUFId;
    }
}

inline void UF_Merge(int parentId, int childId) {
    int parentUFId = UF_find(parentId);
    int childUFId = UF_find(childId);
    UF_Ancestor[childUFId] = parentUFId;
    UF_Ancestor[childId] = parentUFId;
}

int DFSWithUF(int curNodeId) {
    // printf("DFSWithUF %d\n", curNodeId);
    UF_Ancestor[curNodeId] = curNodeId;
    // ancestor[curNodeId] = curNodeId;
    int curChildNodeId = childListHead[curNodeId];
    while(curChildNodeId) {

        if (DFSWithUF(curChildNodeId)) {
            return 1;
        }
        UF_Merge(curNodeId, curChildNodeId);
        // ancestor[UF_find(curNodeId)] = curNodeId;
        curChildNodeId = tree[curChildNodeId].NextBroId;
    }
    // printf("%d is Ved\n", curNodeId);
    fullyVisited[curNodeId] = 1;
    for (int i = 1; i <= querys[curNodeId][0]; i++) {
        if (fullyVisited[querys[curNodeId][i]]) {
            int res = UF_Ancestor[UF_find(querys[curNodeId][i])];
            LCACounter[res]++;
            // printf("FIND %d %d %d %d\n", curNodeId,
            //     querys[curNodeId][i], res, UF_Ancestor[querys[curNodeId][i]]);
            querySolvedNum++;
            if (querySolvedNum == queryNum) {
                return 1;
            }
        }
    }
    return 0;
}

int main() {
    while(scanf("%d", &nodeNum) != EOF) {
        memset(childListHead, 0, sizeof(childListHead));
        memset(tree, 0, sizeof(tree));
        memset(UF_Ancestor, 0, sizeof(UF_Ancestor));
        memset(LCACounter, 0, sizeof(LCACounter));
        memset(querys, 0, sizeof(querys));
        memset(fullyVisited, 0, sizeof(fullyVisited));
        memset(ancestor, 0, sizeof(ancestor));
        querySolvedNum = 0;
        for (int nodeId = 1; nodeId <= nodeNum; nodeId++) {
            int parentId;
            int childId;
            int childNum;
            scanf("%d", &parentId);
            // scanf("%s", nodeInfo);
            while(getchar() != '(');
            scanf("%d", &childNum);
            while(getchar() != ')');
            // parentId = nodeInfo[0] - '0';
            // int childNum = nodeInfo[3] - '0';
            for (int j = 0; j < childNum; j++) {
                scanf("%d", &childId);
                // printf("%d Child %d\n", parentId, childId);
                insertIntoChildList(parentId, childId);
            }
        }

        scanf("%d", &queryNum);

        for (int i = 1; i <= queryNum; i++) {
            int A, B;
            while(getchar() != '(');
            scanf("%d%d", &A, &B);
            while(getchar() != ')');
            querys[A][0]++;
            querys[A][querys[A][0]] = B;
            querys[B][0]++;
            querys[B][querys[B][0]] = A;
        }

        int rootNodeId = 0;
        for (int i = 1; i <= nodeNum; i++) {
            if (tree[i].parentId == 0) {
                rootNodeId = i;
                break;
            }
        }
        DFSWithUF(rootNodeId);
        for (int i = 1; i <= nodeNum; i++) {
            if (LCACounter[i] > 0) {
                printf("%d:%d\n", i, LCACounter[i]);
            }
        }
    }
}

刚搞完1330以后趁热打铁, 原理一样,都是LCA, 只不过这次会有很多的query,因此,如果每次dfs都遍历所有的query的话,基本就TLE了,

因此要搞一个二维矩阵来标示query, query[i][j] 表示与 i 包含在相同query的 第j-1个(query[i][0]表示与i相关的query的数量)node的Id, 每次读入一个query,取到两个点A,B

就更新A 和 B的query矩阵,然后在dfs完某个点k以后,就只遍历query[k][1...N]就可以了,

这里还发现了之前的1330的一个错误,没有加dfs的访问标记vist[], 在每次dfs完某个点以后,就要标示已经visted, 然后下边判断是否是LCA的时候要用是否visted作为标准

被注释掉的ancsteor数组是为了平衡并查集使用的,如果用平衡并查集的话,一个集合的root不一定就是 此集合在树中的根节点。不过如果不使用平衡并查集的话 ,而是直接根据树的结构来合并集合的话,就没有关系.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值