《算法竞赛进阶指南》0x41并查集 NOI2015程序自动分析
题目链接:https://www.acwing.com/problem/content/239/
给出n个变量之间的等式和不等式关系,判断是否存在错误,由于等号具有传递性,不等号不具有,所以可以考虑使用并查集。并查集可以维护图中结点的连通性,在这个问题中得以体现。
其次,这个问题的变量数量少,但是索引大,需要通过离散化进行处理。
代码:
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int maxn =1000010; int n,m; struct node{ int xi,xj; int flag; }p[maxn]; int fa[maxn*2]; int a[maxn*2]; int find(int x){ if(x==fa[x])return x; return fa[x]=find(fa[x]); } int get(int x){ return lower_bound(a+1,a+m+1,x)-a; } void Union(int x,int y){ int fx=find(get(x)); int fy=find(get(y)); if(fx==fy)return ; fa[fx]=fy; return ; } void solve(){ cin>>n; for(int i=1;i<=n;i++){ scanf("%d%d%d",&p[i].xi,&p[i].xj,&p[i].flag); a[2*i-1]=p[i].xi; a[2*i]=p[i].xj; } sort(a+1,a+2*n+1); m=unique(a+1,a+2*n+1)-(a+1); for(int i=1;i<=m;i++)fa[i]=i; for(int i=1;i<=n;i++) if(p[i].flag)Union(p[i].xi,p[i].xj); for(int i=1;i<=n;i++) if(!p[i].flag && find(get(p[i].xi))==find(get(p[i].xj))){ puts("NO"); return ; } puts("YES"); return ; } int main(){ int T; cin>>T; while(T--)solve(); return 0; }
每一个不曾起舞的日子,都是对生命的辜负。