算法设计与优化编程 第十讲 Subway

来源:互联网 发布:施工动画软件 编辑:程序博客网 时间:2024/06/02 00:12

Subway

Problem Description

jiefangxuanyan and yiyi cat are universally acknowledged model couples(配偶). Once jiefangxuanyan has time, he takes a train to yiyi cat’s city and meets her. This time, as usual, jiefangxuanyan gets out from the railway station, and enters the subway, only to find that the subway stations of the whole city changes their names!
As a direction idiot(白痴), jiefangxuanyan felt helpless with this situation. He called yiyi cat for help. Because the subway map is so complicated, she can’t remember it either. Fortunately, only the names of the stations changed, the structure of subway lines is the same. So she picks out the old map to make a mapping.
But mapping such a confused(迷乱的) subway map is definitely a difficult task. So she has to use the computer. Unfortunately, she just spilt(泼出,洒出) wonton(馄饨) soup(汤) into her computer. So, yiyi cat asked you for help, hoping you can help her with this problem.
The subway in the city forms a tree, with N subway stations and N-1 subway lines. Any pair of stations are connected with one or more subway lines. You need to find a bijective(双射) mapping from the old names to the new names, that for each pair of stations connected by exactly one line in the old map, their new names are also connected by exactly one line in the new map.

Input

The input has multiple test cases, please process to the end of file.
For each test case, the first line is an integer N (1≤N≤100000) .
In the following N−1 lines, each line has two space-separated strings, as two stations connected by one line in the old map.
In the following N−1 lines, each line has two space-separated strings, as two stations connected by one line in the new map.
Station names are no longer than 10 characters, and only consists of lowercase letters (a~z).

Output

For each test case, output N lines.
Each line consists two space-separated strings, as the old name and its corresponding new name.
Both the names appeared in the old and new subway map should appear exactly once in the output.
You can output the names in any order. And if there are multiple valid mappings, output any one.
Names in the old map and the new map may be the same, but this does not mean these two stations are the same.

Sample Input

3
a b
b c
b a
a c

Sample Output

b a
a b
c c

这里写图片描述

思路:

这个题是一个树的同构判断,想办法用一个和节点顺序无关的哈希函数将树表示出来即可。
这里提供一种方法:首先求解树的中点,然后将中点作为根。只有一个结点的子树哈希值为1。选一个比较大的质数P和一个特别大的质数Q。对于每一颗树,把它的所有子树的哈希值排序。然后hash=sum(P^i∗hash[i])%Q,就能算出来总体的哈希值。有两个中点的树两个中点都试一下。为了保险可以检查下哈希值有没有重的。

代码

#include <cstring>#include <fstream>#include <string>#include <vector>#include <queue>#include <map>#include <algorithm>#include <iostream>#include <new>using std::string;using std::cin;using std::cout;const int N=110000;struct Metro{    std::map<string,int> mp;    std::vector<string> vec;    //调用分配程序,把字符编号的顶点换成整数编号的顶点    int alloc(const string &name){        //迭代器iterator        std::pair<std::map<string,int>::iterator,bool> got=mp.insert(std::make_pair(name,mp.size()));        //如果得到第二个点        if(got.second){            vec.push_back(name);        }        return got.first->second;    }};//定义item结构体struct item{    int tgt;    item *next;    item(){}    item(int tgt,item *next):tgt(tgt),next(next){}}*ls[N],*lt[N],storage[4*N];//插入边void insert(item **list,int a,int b,item *&loc){    list[a]=new(loc++) item(b,list[a]);    list[b]=new(loc++) item(a,list[b]);}int farSel[N];std::pair<int,int> findFarthest(item **list,int a,int prev){    std::pair<int,int> r(a,-1);    for(item *p=list[a];p;p=p->next){        if(p->tgt!=prev){            std::pair<int,int> cur=findFarthest(list,p->tgt,a);            if(cur.second>r.second){                farSel[a]=p->tgt;                r=cur;            }        }    }    r.second++;    return r;}//找树的中点std::pair<int,int> findRoot(item **list){    int a=findFarthest(list,0,-1).first;    std::pair<int,int> t=findFarthest(list,a,-1);    for(int i=0;i<t.second/2;i++){        a=farSel[a];    }    return std::make_pair(a,t.second%2?farSel[a]:-1);}const int M=1000000007,MM=100000007;struct HashPair{    int a,h;    HashPair(){}    HashPair(int a,int h):a(a),h(h){}    bool operator<(const HashPair &x)const{        return h<x.h;    }};//求哈希值std::vector<HashPair> hs[N],ht[N];int hash(item **list,int a,int prev,std::vector<HashPair> *tgt){    std::vector<HashPair> vec;    for(item *p=list[a];p;p=p->next){        if(p->tgt!=prev){            vec.push_back(HashPair(p->tgt,hash(list,p->tgt,a,tgt)));        }    }    std::sort(vec.begin(),vec.end());    int r=1;    for(int i=0;i<(int)vec.size();i++){        r=((long long)r*MM+vec[i].h)%M;    }    tgt[a].swap(vec);    return r;}bool match(std::vector<HashPair> &vs,std::vector<HashPair> &vt,int *res){    if(vs.size()!=vt.size()){        return false;    }    for(int i=0;i<(int)vs.size();i++){        for(int j=i;j<(int)vt.size()&&vt[j].h==vs[i].h;j++){            std::swap(vt[i].a,vt[j].a);            if(match(hs[vs[i].a],ht[vt[i].a],res)){                goto lblMatch;            }        }        return false;lblMatch:        res[vs[i].a]=vt[i].a;    }    return true;}int mapping[N];int main(){    int size = 8 << 20;    char *p = (char*)malloc(size) + size;    //__asm__("movl %0, %%esp\n" :: "r"(p));    //std::ifstream fin("in.txt");    //std::ofstream fout("out.txt");    int n;    //输入边    while(cin>>n){        memset(ls,0,sizeof(ls));        item *loc=storage;              Metro src;        //转换成整数        for(int i=0;i<n-1;i++){            string name;            cin>>name;            int a=src.alloc(name);            cin>>name;            int b=src.alloc(name);            insert(ls,a,b,loc);        }        memset(lt,0,sizeof(lt));        Metro tgt;        //转换成整数        for(int i=0;i<n-1;i++){            string name;            cin>>name;            int a=tgt.alloc(name);            cin>>name;            int b=tgt.alloc(name);            insert(lt,a,b,loc);        }        //找树根(中点)        std::pair<int,int> rs=findRoot(ls),rt=findRoot(lt);        std::vector<HashPair> vs,vt;        //求树根哈希值        vs.push_back(HashPair(rs.first,hash(ls,rs.first,rs.second,hs)));        //处理第一个中点        if(rs.second!=-1){            vs.push_back(HashPair(rs.second,hash(ls,rs.second,rs.first,hs)));        }        //排序,提高速度        std::sort(vs.begin(),vs.end());        vt.push_back(HashPair(rt.first,hash(lt,rt.first,rt.second,ht)));        //处理第二个中点        if(rs.second!=-1){            vt.push_back(HashPair(rt.second,hash(lt,rt.second,rt.first,ht)));        }        //排序,提高速度        std::sort(vt.begin(),vt.end());        //判断是否同构        if(match(vs,vt,mapping)){            for(int i=0;i<n;i++){                //打印同构                cout<<src.vec[i]<<' '<<tgt.vec[mapping[i]]<<'\n';            }        }else{            cout<<"TAT\n";        }    }    return 0;}
0 0
原创粉丝点击