luogu1955 [NOI2015] 程序自動分析
阿新 • • 發佈:2018-06-02
bool def 排序 sorted 存在 程序 IT clas main
題目大意
假設x1,x2,x3...代表程序中出現的變量,給定n個形如xi=xj或xi≠xj的變量相等/不等的約束條件,請判定是否可以分別為每一個變量賦予恰當的值,使得上述所有約束條件同時被滿足。i,j<=1000000000, n<=1000000
思路
如果把所有相等的變量納為一個或幾個集合,那麽輸出yes當且僅當同一個相等集合中不存在一對xi,xj被要求不相等。集合→並查集。i,j,n的範圍→離散化。
離散化的標準做法
功能
將離散的數據壓縮到一個有限的區間處理。具體可以為輸入一個數的下標,輸出該下標的排名。
實現
將原始下標排序,得到一個下標為原始下標排名順序、值為原始下標的數組。然後我們就可以運用LowerBound二分由原始下標找到其在原數組中的位置了。
註意事項
並查集
- 一開始所有節點的Father都是自己。
- Join兩個節點是將一個節點的Root的Father設為另一個節點的Root,而不是將節點的Father設為另一個節點。
整體
- 如果只想得到70分的話,註意下標範圍是多於N的,所以並查集中的N都應當設為1000000。
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> using namespace std; const int MAX_N = 200010; struct Discret { private: int SortedA[MAX_N]; int Rank[MAX_N]; int N; int LowerBound(int *a, int l, int r, int k) { while (l < r) { int mid = (l + r) / 2; if (k <= SortedA[mid]) r = mid; else l = mid + 1; } return l; } public: void Init(int n, int *a) { N = n; for (int i = 1; i <= n; i++) SortedA[i] = a[i]; sort(SortedA + 1, SortedA + n + 1); int prevVal = 0, rankCnt = 0; for (int i = 1; i <= n; i++) { if (SortedA[i] != prevVal) { Rank[i] = ++rankCnt; prevVal = SortedA[i]; } else Rank[i] = rankCnt; } } int GetRank(int val) { return Rank[LowerBound(SortedA, 1, N, val)]; } }List; struct UnionFind { private: struct Node { Node *Father; }_nodes[MAX_N]; Node *GetRoot(Node *cur) { return cur->Father == cur ? cur : cur->Father = GetRoot(cur->Father); } public: void Init(int n) { for (int i = 1; i <= n; i++) _nodes[i].Father = _nodes + i; } bool SameRoot(int a, int b) { Node *root1 = GetRoot(_nodes + a); Node *root2 = GetRoot(_nodes + b); return root1 == root2; } void Join(int a, int b) { GetRoot(_nodes + a)->Father = GetRoot(_nodes + b); } }G; int main() { #ifdef _DEBUG freopen("c:\\noi\\source\\input.txt", "r", stdin); #endif static vector< pair<int, int> > equal, nequal; static int OrgVal[MAX_N]; int caseCnt; scanf("%d", &caseCnt); while (caseCnt--) { equal.clear(); nequal.clear(); int n; scanf("%d", &n); for (int i = 1; i <= n; i++) { int x1, x2, isEqual; scanf("%d%d%d", &x1, &x2, &isEqual); if (isEqual) equal.push_back(pair<int, int>(x1, x2)); else nequal.push_back(pair<int, int>(x1, x2)); OrgVal[i * 2 - 1] = x1; OrgVal[i * 2] = x2; } List.Init(n * 2, OrgVal); G.Init(n * 2); for (int i = 0; i < equal.size(); i++) { int rank1 = List.GetRank(equal[i].first), rank2 = List.GetRank(equal[i].second); if (!G.SameRoot(rank1, rank2)) G.Join(rank1, rank2); } bool Ok = true; for (int i = 0; i<nequal.size(); i++) { int rank1 = List.GetRank(nequal[i].first), rank2 = List.GetRank(nequal[i].second); if (G.SameRoot(rank1, rank2)) { Ok = false; break; } } if (Ok) printf("YES\n"); else printf("NO\n"); } return 0; }
luogu1955 [NOI2015] 程序自動分析