poj-1470

来源:互联网 发布:mac cs6破解方法 编辑:程序博客网 时间:2024/05/01 04:00
// 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
原创粉丝点击