• [51Nod 1515] 明辨是非


    Description

    (n)组操作,每组操作形式为(x;y;p)
    (p)(1)时,如果第(x)变量和第(y)个变量可以相等,则输出(YES),并限制他们相等;否则输出(NO),并忽略此次操作。
    (p)(0)时,如果第(x)变量和第(y)个变量可以不相等,则输出(YES),并限制他们不相等 ;否则输出(NO),并忽略此次操作。

    Input

    输入一个数(n)表示操作的次数((n<=10^5))
    接下来(n)行每行三个数(x;y;p) ((x,y<=10^8,0≤p≤1))

    Output

    对于(n)行操作,分别输出(n)(YES)或者(NO)

    Solution

    没想到假的启发式合并也能A题啊。。。
    正解其实跟考试时候的思路差不多
    但是不是维护每个联通块的大小
    因为有可能一个联通块大小比较小但是连出去的边有很多
    所以我们要换一种数据结构维护每个联通块连出去了多少条边
    用什么数据结构可以维护大小,快速查找两个元素是否有关系呢?
    嗯... (STL)(set) 是符合要求的 查询大小是 (O(1)) 的,查找是 (O(nlogn))
    所以我们用一个 (set) (s[i]) 表示以 (i) 为根的联通块连出去的边(这里连边表示规定两个联通块严格不相等)
    考虑操作
    如果要求两个变量相等,那么就在两个联通块的 (set) 里找是否存在一条边连到了对方,如果有,那么此条件无法满足。
    如果要求两个变量不相等,那么假设它们不在一个联通块里,需要合并这两个联通块,就要用到启发式合并了。
    注意到我们已经记录了两个联通块连出去边的个数了, 为了保证复杂度,一定是想让连边少的联通块合并到连边多的联通块里。这就是启发式合并了。

    Code

    #include<set>
    #include<map>
    #include<cstdio>
    #define N 100005
    
    int n,tot;
    int ques[N][5];
    int father[N<<1];
    std::map<int,int> mp;
    std::set<int> s[N<<1];
    
    int find(int x){
    	if(father[x]==x) return x;
    	return father[x]=find(father[x]);
    }
    
    signed main(){
    	scanf("%d",&n);
    	for(int x,y,i=1;i<=n;i++){
    		scanf("%d%d%d",&x,&y,&ques[i][3]);
    		if(!mp[x]) mp[x]=++tot;
    		if(!mp[y]) mp[y]=++tot;
    		ques[i][1]=mp[x];
    		ques[i][2]=mp[y];
    	}
    	for(int i=1;i<=tot;i++) father[i]=i;
    	for(int i=1;i<=n;i++){
    		int r1=find(ques[i][1]);
    		int r2=find(ques[i][2]);
    		if(ques[i][3]==1){
    			if(r1==r2) {puts("YES");continue;}
    			if(s[r1].find(r2)!=s[r1].end() or s[r2].find(r1)!=s[r2].end()){
    				puts("NO");
    				continue;
    			}
    			if(s[r1].size()>s[r2].size()) r1^=r2^=r1^=r2;
    			std::set<int>::iterator it;
    			for(it=s[r1].begin();it!=s[r1].end();it++)
    				s[r2].insert(*it),s[*it].insert(r2),s[*it].erase(r1);
    			father[r1]=r2;
    			puts("YES");
    		}
    		else{
    			if(r1==r2) {puts("NO");continue;}
    			if(s[r1].find(r2)!=s[r1].end() or s[r2].find(r1)!=s[r2].end()){
    				puts("YES");
    				continue;
    			}
    			s[r1].insert(r2);
    			s[r2].insert(r1);
    			puts("YES");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    树莓派相关知识
    yum mysql 需要:libsasl2.so.2()(64bit)的解决办法
    python 虚拟环境
    pip 查看某个包有哪些版本并升级
    C# DiagnosticSource and DiagnosticListener
    C# IObservable与IObserver观察者模式
    Visual Studio编译正常,但仍显示红线(Visual studio compiles fine but still shows red lines)
    查看PDB Guid 工具 dumpbin.exe 路径
    VMware vSphere 7.0 安装教程
    gacutil.exe 文件路径
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/8991523.html
Copyright © 2020-2023  润新知