《演算法競賽進階指南》0x41並查集 NOI2015程式自動分析
阿新 • • 發佈:2020-07-13
題目連結: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; }