头像

欢迎来到我的博客

分享题解与总结

P1955 程序自动分析

解题思路:

容易想到用扩展域做

  • "=":朋友
  • "≠":敌人

实际上不需要:

利用等价关系具有传递性

  1. 先处理e=1的条件
  2. 在处理e=0判断是否冲突

注意:

输入的i,j不再是编号1~N,而是1~1e9!——离散化

补充说明:

//样例
10
1 2 1
2 3 1
3 5 1
5 10 1
10 100 1
10000 100 1
1 9999 0
3 2 1
10000 1 0
2 3 1
//离散化结果(偏移量+1之后:)
idx 1  2  3  4  5    6   7     8
val 1  2  3  5  10  100  9999  10000
//对应原式fa[i]
fa  1  2  3  4  5    6   7     8

代码:

struct edge{int x,y,e;};
vector<edge> ed(N);//关系数组
int t,fa[2*N],n,n2,fx,fy,ix,iy;
bool flag;

int find(int x){
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}

void unionset(int a,int b){
	fa[find(a)]=find(b);
}

bool cmp(edge ed1,edge ed2){
	return ed1.e>ed2.e;//先处理"="
}

int main(){
	cin>>t;
	for(int i=0;i<t;++i){
		flag=true;
		vector<int> v;//离散化数组 
		cin>>n;
		for(int j=0;j<n;++j){
			cin>>ed[j].x>>ed[j].y>>ed[j].e;
			v.push_back(ed[j].x);
			v.push_back(ed[j].y);
		}
		sort(ed.begin(),ed.begin()+n,cmp);
		sort(v.begin(),v.end());
		auto it=unique(v.begin(),v.end());
		v.erase(it,v.end());
		n2=v.size();//去重后的元素个数 
		
		for(int j=1;j<=n2;++j) fa[j]=j;//fa[1-n2] 
		for(int j=0;j<n;++j){
			ix=distance(v.begin(),lower_bound(v.begin(),v.end(),ed[j].x))+1;//获得离散化后的下标
			iy=distance(v.begin(),lower_bound(v.begin(),v.end(),ed[j].y))+1;//获得离散化后的下标
			if(ed[j].e==1) unionset(ix,iy);
			else{
				fx=find(ix);
				fy=find(iy);
				if(fx==fy){//冲突
					flag=false;
					break;
				}
			}
		}
		if(flag) cout<<"YES\n";
		else cout<<"NO\n";
	}
	return 0;
}
posted @ 2026-06-22 14:44  king_steph1209  阅读(11)  评论(0)    收藏  举报