HDU 5732 Subway

给定两棵同构的树,要求输出对应的点对。
Hash

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<bitset>
#include<queue>
#include<cmath>
#include<ctime>
#include<map>
#define inf (1<<30)
#define INF (1ll<<62)
#define fi first
#define se second
#define prt(x) cout<<#x<<":"<<x<<" "
#define prtn(x) cout<<#x<<":"<<x<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
template<class T>void sc(T &x){
    int f=1;x=0;char c;
    while(c=getchar(),c<48)if(c=='-')f=-1;
    do x=x*10+(c^48);
    while(c=getchar(),c>47);
    x*=f;
}
template<class T>void nt(T x){
    if(!x)return;
    nt(x/10);putchar('0'+x%10);
}
template<class T>void pt(T x){
    if(x<0)putchar('-'),x=-x;
    if(!x)putchar('0');
    else nt(x);
}
int n;
const int maxn=100005;

int last[2][maxn],ecnt;
struct Edge{
    int to,nxt;
    Edge(){}
    Edge(int a,int b):to(a),nxt(b){}
}e[maxn<<2];
void ins(int *last,int u,int v){
    e[ecnt]=Edge(v,last[u]);
    last[u]=ecnt++;
}

struct abcd{
    vector<string>a;
    map<string,int>b;
    void init(){
        a.clear();
        b.clear();
    }
    int operator [] (string c){
        if(b.find(c)!=b.end())return b[c];
        a.push_back(c);
        return b[c]=a.size();;
    }
    string operator [] (int c){
        return a[c-1];
    }
}name;

ii RT;
int sz[maxn];
void dfs(int *last,int x,int f){
    sz[x]=1;
    bool ok=true;
    for(int i=last[x];i!=-1;i=e[i].nxt){
        int to=e[i].to;
        if(to==f)continue;
        dfs(last,to,x);
        ok&=sz[to]<=n/2;
        sz[x]+=sz[to];
    }ok&=(n-sz[x])<=n/2;
    if(!ok)return;
    if(RT.fi==-1)RT.fi=x;
    else RT.se=x;
}
void find_rt(int *last){
    RT.fi=RT.se=-1;
    dfs(last,1,0);
}

int has[2][maxn];//val,id
int H[maxn];
int link[maxn];

const int Pa=674679;//4679
const int Pb=165537;//65537
const int Pp=435617;//35617
const int Pq=1000000033;
void gethash(int *has,int *last,int x,int f){
    for(int i=last[x];i!=-1;i=e[i].nxt){
        int to=e[i].to;
        if(to!=f)gethash(has,last,to,x);
    }
    int tot=0;
    for(int i=last[x];i!=-1;i=e[i].nxt){
        int to=e[i].to;
        if(to!=f)H[++tot]=has[to];
    }
    sort(H+1,H+tot+1);

    ll res=Pa;
    for(int i=1;i<=tot;i++)
        res=(res*Pp^H[i])%Pq;
    res=res*Pb%Pq;

    has[x]=res;
}
ii HA[maxn],HB[maxn];
bool chk(int x,int fx,int y,int fy){
    int na,nb;na=nb=0;
    for(int i=last[0][x];i!=-1;i=e[i].nxt){
        int to=e[i].to;
        if(to==fx)continue;
        HA[++na]=ii(has[0][to],to);
    }
    for(int i=last[1][y];i!=-1;i=e[i].nxt){
        int to=e[i].to;
        if(to==fy)continue;
        HB[++nb]=ii(has[1][to],to);
    }
    if(na!=nb)return false;
    sort(HA+1,HA+na+1);
    sort(HB+1,HB+nb+1);
    for(int i=1;i<=na;i++){
        if(HA[i].fi!=HB[i].fi)return false;
        link[HA[i].se]=HB[i].se;
    }
    for(int i=last[0][x];i!=-1;i=e[i].nxt){
        int to=e[i].to;
        if(to==fx)continue;
        if(!chk(to,x,link[to],y))return false;
    }
    return true;
}
bool match(int x,int y){
    gethash(has[0],last[0],x,0);
    gethash(has[1],last[1],y,0);
    if(has[0][x]!=has[1][y])return false;
    link[x]=y;
    return chk(x,0,y,0);
}

void output(){
    for(int i=1;i<=n;i++)
        cout<<name[i]<<" "<<name[link[i]]<<endl;
}

void solve(){
    string u,v;
    name.init();
    ecnt=0;
    for(int i=0;i<2;i++){
        memset(last[i],-1,n+1<<2);
        for(int a,b,j=1;j<n;j++){
            cin>>u>>v;
            a=name[u];
            b=name[v];
            ins(last[i],a,b);
            ins(last[i],b,a);
        }
    }

    ii rt[2];
    for(int i=0;i<2;i++){
        find_rt(last[i]);
        rt[i]=RT;
    }
//  for(int i=0;i<2;i++)
//      prt(rt[i].fi),prtn(rt[i].se);
    if(match(rt[0].fi,rt[1].fi))output();
    else if(match(rt[0].fi,rt[1].se))output();
    else puts(":{");
}

int main(){
//  freopen("pro.in","r",stdin);
//  freopen("chk.out","w",stdout);
    while(~scanf("%d",&n))solve();//*INF
    return 0;
}

以及造数据的程序 :{

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<bitset>
#include<queue>
#include<cmath>
#include<ctime>
#define inf (1<<30)
#define INF (1ll<<62)
#define prt(x) cout<<#x<<":"<<x<<" "
#define prtn(x) cout<<#x<<":"<<x<<endl
using namespace std;
typedef long long ll;
template<class T>void sc(T &x){
    int f=1;x=0;char c;
    while(c=getchar(),c<48)if(c=='-')f=-1;
    do x=x*10+(c^48);
    while(c=getchar(),c>47);
    x*=f;
}
template<class T>void nt(T x){
    if(!x)return;
    nt(x/10);putchar('0'+x%10);
}
template<class T>void pt(T x){
    if(x<0)putchar('-'),x=-x;
    if(!x)putchar('0');
    else nt(x);
}
const int n=100000;
struct Edge{
    int u,v;
}edge[n+5];
int f[n+5];
int Rand(){
    return rand()<<15|rand();
}
int main(){
    srand(time(0));
    freopen("pro.in","w",stdout);
    printf("%d\n",n);
    for(int i=2;i<=n;i++)
        edge[i]=(Edge){Rand()%(i-1)+1,i};
    for(int i=2;i<=n;i++)
        printf("%d %d\n",edge[i].u,edge[i].v);
    for(int i=1;i<=n;i++)
        f[i]=i,swap(f[i],f[Rand()%i+1]);
    for(int i=1;i<=100000;i++){
        int u=Rand()%n+1,v=Rand()%n+1;
        if(u!=1&&v!=1)swap(edge[u],edge[v]);    
    }
    for(int i=2;i<=n;i++){
        printf("%d %d\n",f[edge[i].u],f[edge[i].v]);
    }
    return 0;
}

启发式合并+树的最小表示法

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值