POJ 1635 树的最小表示法/HASH

Posted キリト

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1635 树的最小表示法/HASH相关的知识,希望对你有一定的参考价值。

 

题目链接:http://poj.org/problem?id=1635

题意:给定两个由01组成的串,0代表远离根,1代表接近根。相当于每个串对应一个有根的树。然后让你判断2个串构成的树是否是同构的。

思路:首先根据01串构造出树,然后求树的最小表示法判断同构。 详情参照:https://www.byvoid.com/blog/directed-tree-bracket-sequence/ 

 

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long int LL;
const int MAXN=3000+5;
int fa[MAXN];
char strA[MAXN],strB[MAXN];
vector<int>treeA[MAXN],treeB[MAXN];
void build(char *s,vector<int>tree[MAXN]){
    int hashNum=1,now=0,len=strlen(s);
    for(int i=0;i<MAXN;i++){
        tree[i].clear();
    }
    for(int i=0;i<len;i++){
        if(s[i]==0){
            fa[hashNum]=now;
            tree[now].push_back(hashNum);
            now=hashNum++;
        }
        else{
            now=fa[now];
        }
    }
}
string dfs(int now,vector<int>tree[MAXN]){
    vector<string>HashC;
    for(int i=0;i<tree[now].size();i++){
        HashC.push_back(dfs(tree[now][i],tree));
    }
    string Hash="(";
    sort(HashC.begin(),HashC.end());
    for(int i=0;i<HashC.size();i++){
        Hash+=HashC[i];
    }
    Hash+=")";
    return Hash;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%s",strA); scanf("%s",strB);
        memset(fa,0,sizeof(fa));build(strA,treeA);
        memset(fa,0,sizeof(fa));build(strB,treeB);
        if(dfs(0,treeA)==dfs(0,treeB)){
            printf("same\n");
        }
        else{
            printf("different\n");
        }
    }
    return 0;
}

 

思路2:HASH,思路参照:集训队论文:杨弋《Hash在信息学竞赛中的一类应用》

题目卡的比较死。 参数不好拿捏。最好进行Double HASH比较保险

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<vector>
using namespace std;
typedef long long int LL;
typedef unsigned int uint;
const int MAXN=3000+5;
const int MODF=1e9+7;
const int MODS=1e9+7;
int fa[MAXN],HF[MAXN],HS[MAXN];
char strA[MAXN],strB[MAXN];
vector<int>treeA[MAXN],treeB[MAXN];
void build(char *s,vector<int>tree[MAXN]){
    int hashNum=1,now=0,len=strlen(s);
    for(int i=0;i<MAXN;i++){
        tree[i].clear();
    }
    for(int i=0;i<len;i++){
        if(s[i]==0){
            fa[hashNum]=now;
            tree[now].push_back(hashNum);
            now=hashNum++;
        }
        else{
            now=fa[now];
        }
    }
}
pair<int,int> dfs(int now,vector<int>tree[MAXN]){
    int HashNumF=1,HashNumS=1;
    vector<pair<int,int> >HashC;
    for(int i=0;i<tree[now].size();i++){
        HashC.push_back(dfs(tree[now][i],tree));
    }
    sort(HashC.begin(),HashC.end());
    for(int i=0;i<HashC.size();i++){
        HashNumF=((HashNumF^HashC[i].first)*HF[i])%MODF;
        HashNumS=((HashNumS^HashC[i].second)*HS[i])%MODS;
    }
    return make_pair(HashNumF%MODF,HashNumS%MODS);
}
int main()
{
    for(int i=0;i<MAXN;i++){
        HF[i]=rand()%MODF;
        HS[i]=rand()%MODS;
    }
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%s",strA); scanf("%s",strB);
        memset(fa,0,sizeof(fa));build(strA,treeA);
        memset(fa,0,sizeof(fa));build(strB,treeB);
        pair<int,int>TA=dfs(0,treeA);
        pair<int,int>TB=dfs(0,treeB);
        if(TA.first==TB.first&&TA.second==TB.second){
            printf("same\n");
        }
        else{
            printf("different\n");
        }
    }
    return 0;
}

 

以上是关于POJ 1635 树的最小表示法/HASH的主要内容,如果未能解决你的问题,请参考以下文章

POJ1635 Subway tree systems ——(判断树的同构,树的最小表示法)

poj 1635 Subway tree systems(树的最小表示)

Godfather(POJ3107)——求树的重心(递归)

bzoj4435: [Cerc2015]Juice Junctions(最小割树+hash)

POJ1635Subway tree systems

poj1679(判断最小生成树的唯一性)