• 树的同构问题


    似乎树的重心个数是(O(1))的?

    那么对于每个重心以他为根最小表示法判断子树...

    递归处理...先对于每棵子树处理,然后将子树按最小表示法排序.排序关键字就是每一层的儿子数?反正可以O(子树大小)比较一次...可以加一点hash,等数据的比较来优化速度...

    这部分的时间似乎是(T(n)=p T(n/p)+O(plog{p}*frac{n}{p})=O(nlog{n}))...然后就没了?

    不懂哦..求教

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    #define maxn 2000100
    using namespace std;
    #define pushvc(_v,_t) _v.push_back(_t)
    #define hashmod 998244353
    namespace graph{
    	struct node;
    	struct edge{
    		node* t;
    		edge* n;
    		edge(node* t=NULL,edge* n=NULL):t(t),n(n){}
    	};
    	struct node{
    		int id;
    		edge* h;
    		node(int id=0,edge* h=NULL):id(id),h(h){}
    	};
    	struct graph{ // utility for storing a graph, and later convert to a tree
    		node nodes[maxn];
    		edge edges[maxn<<1];
    		int edgeSize,nodeCount;
    		graph(int edgeSize=0,int nodeCount=0):edgeSize(edgeSize),nodeCount(nodeCount){}
    		inline void addedge(node* a,node* b){
    			++edgeSize;
    			edges[edgeSize]=(edge){b,a->h};
    			a->h=edges+edgeSize;
    		}
    		inline void bidedge(node* a,node* b){
    			addedge(a,b); addedge(b,a);
    		}
    		inline node* newNode(){
    			++nodeCount;
    			nodes[nodeCount].id=nodeCount;
    			return nodes+nodeCount;
    		}
    		inline node& operator[](int n){
    			return nodes[n];
    		}
    		inline node* operator+ (int n){
    			return nodes+n;
    		}
    	};
    	struct unrooted_tree{
    		struct node_data{
    			int tot_sub,max_sub;
    		} nt_nds[maxn];
    		graph grf;
    		int size;
    		node* wc[10];
    		int sizewc;
    		int mimasubtree;
    		unrooted_tree(int _size=0){
    			size=_size;
    			if(_size){
    				while(_size){
    					grf.newNode();
    					--_size;
    				}
    			}
    		}
    		inline int _gwc_dfs(node* n,node* f){
    			nt_nds[n->id].max_sub=0;
    			nt_nds[n->id].tot_sub=1;
    			for(edge* i=n->h;i;i=i->n){
    				if(i->t == f) continue;
    				int q=_gwc_dfs(i->t,n);
    				nt_nds[n->id].tot_sub+=q;
    				if(q > nt_nds[n->id].max_sub) nt_nds[n->id].max_sub=q;
    			}
    			if((size-nt_nds[n->id].tot_sub) > nt_nds[n->id].max_sub)
    				nt_nds[n->id].max_sub=size-nt_nds[n->id].tot_sub;
    			return nt_nds[n->id].tot_sub;
    		}
    		inline void pushwc(node* p){
    			wc[++sizewc]=p;
    		}
    		inline int getwcs(){ // get weight centers, return the number of weight centers.
    			_gwc_dfs(grf+1,NULL);
    			mimasubtree=0x7fffffff;
    			sizewc=0;
    			for(int i=1;i<=size;++i) if(nt_nds[i].max_sub < mimasubtree) mimasubtree=nt_nds[i].max_sub;
    			for(int i=1;i<=size;++i) if(nt_nds[i].max_sub== mimasubtree) pushwc(grf+i);
    			return sizewc;
    		}
    		FILE* otd; // for dot file output
    		inline void _print_dfs(node* n,node* f){
    			fprintf(otd,"A%d[label="#%d"];
    ",n->id,n->id);
    			for(edge* i=n->h;i;i=i->n){
    				if(i->t == f) continue;
    				fprintf(otd,"A%d -> A%d;
    ",n->id,i->t->id);
    				_print_dfs(i->t,n);
    			}
    		}
    		inline void print_dot(node* asroot){
    			fprintf(otd,"digraph{
    "
    					"	node[color="#2266ff",fillcolor="#aaccff",fontname="Courier",regular=true];
    ");
    			_print_dfs(asroot,NULL);
    			fprintf(otd,"}
    ");
    		}
    		inline void openOutputFile(const char* filename){
    			if(otd) fclose(otd),otd=NULL;
    			otd=fopen(filename,"w");
    		}
    	};
    //	FILE* otd; // for dot file output
    //	inline void mopenOutputFile(const char* filename){
    //		if(otd) fclose(otd),otd=NULL;
    //		otd=fopen(filename,"w");
    //	}
    	struct rooted_tree{
    		int size,maxdepth,hash;
    		node* root;
    		vector<rooted_tree*> sons;
    		void build(node* p,node* f);
    		void print();
    	};
    	inline int cmp_same (rooted_tree* a,rooted_tree* b){
    		if(a->size - b->size) return a->size - b->size;
    		if(a->maxdepth - b->maxdepth) return a->maxdepth - b->maxdepth;
    		if(a->hash - b->hash) return a->hash - b->hash;
    		int ax=a->sons.size(),bx=b->sons.size();
    		if(ax - bx) return ax - bx;
    		for(int i=0;i<ax;++i){
    			int q=cmp_same(a->sons[i],b->sons[i]);
    			if(q) return q;
    		}
    		return 0;
    	}
    	inline bool cmp_build(const rooted_tree* a,const rooted_tree* b){
    		if(a->size - b->size) return a->size > b->size;
    		if(a->maxdepth - b->maxdepth) return a->maxdepth > b->maxdepth;
    		if(a->hash - b->hash) return a->hash > b->hash;
    		int ax=a->sons.size(),bx=b->sons.size();
    		if(ax - bx) return ax > bx;
    		for(int i=0;i<ax;++i){
    			int q=cmp_same(a->sons[i],b->sons[i]);
    			if(q) return q>0;
    		}
    		return 0;
    	}
    	void rooted_tree::build(node* p,node* f){
    		root=p; size=1; maxdepth=0; hash=1;
    		for(edge* i=p->h;i;i=i->n){
    			if(i->t == f) continue;
    			rooted_tree* s1=new rooted_tree;
    			s1->build(i->t,p);
    			pushvc(sons,s1);
    			size+=s1->size;
    			if(s1->maxdepth > maxdepth) maxdepth=s1->maxdepth;
    		}
    		++maxdepth;
    		sort(sons.begin(),sons.end(),cmp_build);
    		for(int i=0,_=sons.size();i<_;++i){
    			hash=((long long)hash+(long long)sons[i]->hash*(long long)(i+1))%hashmod;
    			//some very weak hash function, because the time complexity is
    			//provided O(nlogn) total, so it is just a speed up
    		}
    	}
    	bool isiso(unrooted_tree* a,unrooted_tree* b){
    		if(a->size != b->size) return 0;
    		a->getwcs();
    		int q=b->getwcs();
    		if(a->sizewc != b->sizewc) return 0;
    		if(a->mimasubtree != b->mimasubtree) return 0;
    		rooted_tree* ptree=new rooted_tree;
    		ptree->build(a->wc[1],NULL); // build an minimized tree
    		for(int i=1;i<=q;++i){
    			rooted_tree* qtree=new rooted_tree;
    			qtree->build(b->wc[i],NULL);
    			if(!cmp_same(ptree,qtree)) return 1;
    		}
    		return 0;
    	}
    	inline unrooted_tree* readTree_byEdge(){
    		int n;
    		scanf("%d",&n);
    		unrooted_tree* p=new unrooted_tree(n);
    		for(int i=1,a,b;i<n;++i){
    			scanf("%d%d",&a,&b);
    			p->grf.bidedge(p->grf+a,p->grf+b);
    		}
    		return p;
    	}
    	void rooted_tree::print(){
    		printf("Access node %d with %d sons,Fields: size %d maxdepth %d hash%d
    ",
    			root->id,sons.size(),size,maxdepth,hash);
    		if(sons.size()){
    			printf("Sons:");
    			for(int i=0;i<sons.size();++i) printf("%d ",sons[i]->root->id);
    			putchar('
    ');
    			for(int i=0;i<sons.size();++i) sons[i]->print();
    		}
    	}
    }
    using namespace graph;
    int main(){
    	unrooted_tree* p=readTree_byEdge();
    	unrooted_tree* q=readTree_byEdge();
    //	p->openOutputFile("out.dot");
    //	p->getwcs();
    //	p->print_dot(p->wc[1]);
    //	printf("%d %d %d
    ",p->wc[1]->id,p->mimasubtree,p->wc[2]->id);
    //	rooted_tree* k=new rooted_tree;
    //	k->build(p->wc[1],NULL);
    //	k->print();
    //	rooted_tree* kq=new rooted_tree;
    //	if(p->wc[2]){
    //		kq->build(p->wc[2],NULL);
    //		kq->print();
    //		printf("%s
    ",cmp_same(k,kq)?"Diff":"Same");
    //	}
    	printf("%s
    ",isiso(p,q)?"Same":"Diff");
    	return 0;
    }
    
  • 相关阅读:
    vscode debugger 调试服务
    巴克斯诺尔范式 && 乔姆斯基谱系,词法 && 语法
    推荐好用的建站系统以及各网站系统优缺点介绍
    解决emlog默认导航不能修改的问题以及修改后台登录地址的方法
    易企CMS主要模板文件介绍
    易企CMS模板调用标签列表
    易企CMS仿站标签说明
    使用Custom scrollbar(彩色滚动条)插件实现WordPress滚动条变色的方法
    2018给网页滚动条变色的新方法
    javascript实现双击网页自动滚动,单击滚动停止
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4951249.html
Copyright © 2020-2023  润新知