zoukankan      html  css  js  c++  java
  • [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;
    }
    

  • 相关阅读:
    利用qt打开一张图片并转成灰度矩阵
    适配手机端浏览器
    ps常用快捷键(供自己学习查看)
    用选框工具画圆角矩形
    ps制作有背景图片的字体
    所有iOS 设备的屏幕尺寸
    九宫格有规律高亮滚动效果
    移动端点击事件全攻略
    移动端ios升级到11及以上时,手机弹框输入光标出现错位问题
    linux下截取整个网页
  • 原文地址:https://www.cnblogs.com/Troverld/p/14605851.html
Copyright © 2011-2022 走看看