POJ - 1733 Parity game 离散化+带权并查集

题目链接

POJ-1733

题意

一个只含01的串,告诉你a-b的1的个数的奇偶性,问第几句话开始矛盾

思路

带权并查集,va数组表示父父节点间存在的1的个数的奇偶性,因为n太大了所以需要离散化。离散化学了没咋用过,带权并查集几天不写又全忘了,wa到头疼,思路没难度,之前博客写过类似题,注释多写了些,看代码吧,不懂可以翻翻我之前的带权并查集博客。

代码

#include<iostream>  
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<map>
#include<string>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
using namespace std;
	typedef long long ll;
	const int maxn=50500;//别问,问就是开越大越好 ^^ 
	const int inf=0x3f3f3f3f;
	int fa[maxn];
	int va[maxn];//1奇数,0偶数 
	int a[maxn],b[maxn];//b数组没用,懒得删了 
	struct Node{
    
    
		int x,y,z;
	}node[maxn];//离线操作,存一下 
	int n,q;
	
	void init(){
    
    
		for(int i=0;i<maxn;i++){
    
    
			va[i]=0;//初始化为0,自己跟自己的1个数肯定为0,也就是偶数 
			fa[i]=i;
		}
	}
	int find(int x){
    
    
		if(x==fa[x])
			return x;//直接返回 
		int t=find(fa[x]);
		va[x]^=va[fa[x]];//va维护的是和父节点的关系,如果要路径压缩的话需要异或上父节点value
		//至于为什么异或,0代表偶,1代表奇,自己模拟下就行了 
		return fa[x]=t;//路径压缩优化 
	}
	void unite(int x,int y,int z){
    
    
		int fx=find(x),fy=find(y);
		if(fx==fy)
			return ;
		fa[fx]=fy;
		va[fx]=va[x]^va[y]^z;//建议画图手推,可以看我第一篇带权并查集博客,有一张推find函数的思路图 
	}
	int main(){
    
    
		IOS
		cin>>n>>q;
		init();
		int p=1;
		for(int i=1;i<=q;i++){
    
    
			int x,y;
			cin>>x>>y;
			
			x--;//xy包含端点,处理下x--或者y++ 
			a[p]=x;
			node[i].x=x;
			p++;
			
			a[p]=y;
			node[i].y=y;
			p++;
			
			string s;
			cin>>s;
			if(s=="even")
				node[i].z=0;
			else
				node[i].z=1;	
		}
		//离散化部分 
		p--;
		sort(a+1,a+1+p);
		int len=unique(a+1,a+p+1)-a-1;
		
		int ans=q;
		for(int i=1;i<=q;i++){
    
    
			int x=lower_bound(a+1,a+len+1,node[i].x)-a;
			int y=lower_bound(a+1,a+len+1,node[i].y)-a;
			int fx=find(x),fy=find(y);
			if(fx!=fy)
				unite(x,y,node[i].z);
			else{
    
    
				if(va[x]^va[y]!=node[i].z){
    
    
					ans=i-1;
					break;
				}
			}
		}
		cout<<ans<<endl;
	}
	

猜你喜欢

转载自blog.csdn.net/TheSunspot/article/details/108031335
今日推荐