【並查集】B001_AW_自動程式分析(不要求順序時的離散化)
阿新 • • 發佈:2020-09-09
考慮一個約束滿足問題的簡化版本:假設x1,x2,x3,…代表程式中出現的變數,給定n個形如xi=xj或xi≠xj的變數相等/不等的約束條件,請判定是否可以分別為每一個變數賦予恰當的值,使得上述所有約束條件同時被滿足。
例如,一個問題中的約束條件為:x1=x2,x2=x3,x3=x4,x1≠x4,這些約束條件顯然是不可能同時被滿足的,因此這個問題應判定為不可被滿足。
現在給出一些約束滿足問題,請分別對它們進行判定。
資料範圍
1≤n≤1000000
1≤i,j≤1000000000
輸入樣例:
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1
輸出樣例:
NO
YES
方法一:離散化+並查集
x 最多會有 1e9 個,但 n 最大為 1e6,所以有 1e9-2e6 個數是可以不用的,故需要對資料進行離散化
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e6+5; struct node{ int u,v,e; }; int id; node A[N]; int fa[N]; unordered_map<int, int> m; int get(int u) { if (m.find(u)==m.end()) m[u]=++id; return m[u]; } int find(int u) { return fa[u]==u ? u : fa[u]=find(fa[u]); } int main() { std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin>>t; while (t--) { int n,u,v,e; cin>>n; for (int i=0; i<n; i++) { cin>>u>>v>>e; A[i]={get(u), get(v), e}; } for (int i=1; i<=id; i++) fa[i]=i; for (int i=0; i<n; i++) if (A[i].e) { int fa_u=find(A[i].u), fa_v=find(A[i].v); if (fa_u != fa_v) { fa[fa_u]=fa_v; } } bool valid=true; for (int i=0; i<n; i++) if (!A[i].e) { int fa_u=find(A[i].u), fa_v=find(A[i].v); if (fa_u == fa_v) { valid=false; break; } } cout << (valid ? "YES" : "NO") << '\n'; m.clear(); } return 0; }
複雜度分析
- Time:\(O(nlogn)\),
- Space:\(O(n)\),