【哈希】【动态规划】[NOIP模拟赛]仔细的检查

来源:互联网 发布:产品外观结构设计软件 编辑:程序博客网 时间:2024/05/22 07:51

nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上。另一天nodgd更无聊,就又画了一张。
这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点u0在第一幅图中编号为u1,在第二副图中编号为u2。
于是,nodgd决定检查一下他画出的两棵树到底是不是一样的。nodgd已经给每棵树的节点都从1到n进行了编号,即每棵树有n个节点。
如果存在一个1到n的排列p1,p2…pn,对于第一幅图中的任意一条边(i,j),在第二幅图中都能找到一条边(pi,pj),则认为这两幅图中的树是一样的。

题目解析:
把整个数hash一下,然后比较,同时按照size进行排序重新建树,最后dfn值进行匹配输出就好了

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <iostream>using namespace std;const int MAXN=200005;const int MAXM=400005;const int IFN=999999999;const long long MOD=1000000000000007LL;const int RAN = 10097;struct node{int v;node *next;};pair<long long, int> tmp[MAXN+10];int n;struct Tree{    int dcnt, dep[MAXN+10], Fa[MAXN+10];    node Edges[MAXM*2 + 10], Edges2[MAXM*2 + 10];    long long hash_val[MAXN+10];    int sz[MAXN+10], dfn[MAXN+10];    node *adj[MAXN+10], *adj2[MAXN+10], *ecnt, *ecnt2;    Tree(){        dcnt=0;        ecnt=Edges;        ecnt2=Edges2;    }    void addedge(int u, int v){        ++ecnt;        ecnt->v = v;        ecnt->next = adj[u];        adj[u] = ecnt;    }    void addedge2(int u, int v){        ++ecnt2;        ecnt2->v = v;        ecnt2->next = adj2[u];        adj2[u] = ecnt2;    }    void dfs1(int u, int fa){        sz[u] = 1;        for(node *p=adj[u];p;p=p->next){            if(p->v != fa){                dfs1(p->v, u);                sz[u] += sz[p->v];            }        }        int cnt = 0;        for(node *p=adj[u];p;p=p->next)            if(p->v != fa)                tmp[++cnt] = make_pair(hash_val[p->v], p->v);        sort(tmp+1, tmp+1+cnt);        hash_val[u] = (0 ^ sz[u]) % MOD;        for(int i=1;i<=cnt;i++){            hash_val[u] = (hash_val[u] * RAN ^ (tmp[i].first)) % MOD;            addedge2(u, tmp[i].second);        }    }    void dfs2(int u, int fa){        if(u <= n)            dfn[++dcnt] = u;        for(node *p=adj2[u];p;p=p->next)            if(p->v != fa)                dfs2(p->v, u);    }    int FindMID(){        int Max = 0, ret = -1;        queue<pair<int, int> > que;        que.push(make_pair(1, 0));        while(!que.empty()){            pair<int, int> u = que.front(); que.pop();            for(node *p=adj[u.first];p;p=p->next){                if(p->v != u.second){                    dep[p->v] = dep[u.first] + 1;                    que.push(make_pair(p->v, u.first));                    if(dep[p->v] > Max){                        Max = dep[p->v];                        ret = p->v;                    }                }            }        }        que.push(make_pair(ret, 0));        dep[ret] = 0;        Max = 0; ret = -1;        while(!que.empty()){            pair<int, int> u = que.front(); que.pop();            for(node *p=adj[u.first];p;p=p->next){                if(p->v != u.second){                    dep[p->v] = dep[u.first] + 1;                    que.push(make_pair(p->v, u.first));                    if(dep[p->v] > Max){                        Max = dep[p->v];                        ret = p->v;                    }                    Fa[p->v] = u.first;                }            }        }        Max /= 2;        int now = ret;        while(Max--)            now = Fa[now];        return now;    }    int Read(){        int u, v;        for(int i=1;i<n;i++){            scanf("%d%d", &u, &v);            addedge(u, n+i); addedge(n+i, u);            addedge(v, n+i); addedge(n+i, v);        }        int md = FindMID();        dfs1(md, -1); dfs2(md, -1);        return hash_val[md];    }}Tree1, Tree2;int con[MAXN+10];int main(){    scanf("%d", &n);    int h1 = Tree1.Read();    int h2 = Tree2.Read();    if(h1 != h2) printf("NO\n");    else{        printf("YES\n");        for(int i=1;i<=n;i++)            con[Tree1.dfn[i]] = Tree2.dfn[i];        for(int i=1;i<=n;i++)            printf("%d ", con[i]);    }    return 0;}
1 0
原创粉丝点击