• [URAL2085]Magic Programmer


    XIV.[URAL2085]Magic Programmer

    如何处理路径上所有东西出现且只出现一次的限制呢?我们考虑哈希。只需要用一个哈希表处理所有出现过的东西,然后求另一半东西时,找出它的补集的哈希值在哈希表中查询,即可做到路径拼接。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ull;
    const int bas1=17680321,bas2=19260817;
    struct HASH:pair<ull,ull>{
    	void operator ^=(const HASH &x){first^=x.first,second^=x.second;}
    }hs[100100],now1,now2;
    map<HASH,pair<int,int> >mp;
    int n,m,sz[100100],msz[100100],ROOT,SZ,cnt1[100100],cnt2[100100],resu,resv,resw;
    vector<int>v[100100],u[100100];
    bool vis[100100];
    void getroot(int x,int fa){
    	msz[x]=0,sz[x]=1;
    	for(auto y:v[x])if(y!=fa&&!vis[y])getroot(y,x),sz[x]+=sz[y],msz[x]=max(msz[x],sz[y]);
    	msz[x]=max(msz[x],SZ-sz[x]);
    	if(msz[x]<msz[ROOT])ROOT=x;
    }
    void getsz(int x,int fa){
    	sz[x]=1;
    	for(auto y:v[x])if(y!=fa&&!vis[y])getsz(y,x),sz[x]+=sz[y];
    }
    void getwrite(int x,int fa,int DEP){
    	bool ok=true;
    	for(auto i:u[x])if(!cnt1[i]++)now1^=hs[i];else ok=false;
    	if(ok){
    		mp[now1]=max(mp[now1],make_pair(DEP,x));
    		for(auto y:v[x])if(y!=fa&&!vis[y])getwrite(y,x,DEP+1);		
    	}
    	for(auto i:u[x])if(!--cnt1[i])now1^=hs[i];
    }
    void getread(int x,int fa,int DEP){
    	bool ok=true;
    	for(auto i:u[x])if(!cnt2[i]++)now2^=hs[i];else ok=false;
    	if(ok){
    		if(mp.find(now2)!=mp.end()){
    			auto tmp=mp[now2];
    			if(tmp.first+DEP>resw)resw=tmp.first+DEP,resu=tmp.second,resv=x;
    		}
    		for(auto y:v[x])if(y!=fa&&!vis[y])getread(y,x,DEP+1);		
    	}
    	for(auto i:u[x])if(!--cnt2[i])now2^=hs[i];
    }
    void getans(int x){
    	for(auto i:u[x])if(!cnt1[i]++)now1^=hs[i];
    	mp[now1]=max(mp[now1],make_pair(1,x));
    	for(auto y:v[x])if(!vis[y])getread(y,x,1),getwrite(y,x,2);
    	for(auto i:u[x])if(!--cnt1[i])now1^=hs[i];
    	mp.clear();
    }
    void solve(int x){
    	getans(x),getsz(x,0),vis[x]=true;
    	for(auto y:v[x])if(!vis[y])ROOT=0,SZ=sz[y],getroot(y,0),solve(ROOT);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	hs[0].first=hs[0].second=1;for(int i=1;i<=m;i++)hs[i].first=hs[i-1].first*bas1,hs[i].second=hs[i-1].second*bas2,now2^=hs[i];
    	for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
    	for(int i=1,x,y;i<=n;i++){
    		scanf("%d",&x);
    		if(x==m)resu=resv=i,resw=1;
    		while(x--)scanf("%d",&y),u[i].push_back(y);
    	}
    	SZ=n,msz[0]=n+1,getroot(1,0),solve(ROOT);
    	if(!resw)puts("No solution");else printf("%d %d\n",resu,resv);
    	return 0;
    }
    

  • 相关阅读:
    学习些新东西
    浏览器内的web开发工具
    基于oracle开发的初步接触
    LAMP3 PHP安装
    svn for windows
    PHP替换掉字符串中的非字符
    搭个邮件服务器
    centos下安装mysql
    安装tomcat
    c#线程
  • 原文地址:https://www.cnblogs.com/Troverld/p/14605851.html
Copyright © 2020-2023  润新知