1. 程式人生 > 其它 >洛谷 P1955 [NOI2015] 程式自動分析

洛谷 P1955 [NOI2015] 程式自動分析

https://www.luogu.com.cn/problem/P1955

題目描述

在實現程式自動分析的過程中,常常需要判定一些約束條件是否能被同時滿足。

考慮一個約束滿足問題的簡化版本:假設x1,x2,x3,⋯代表程式中出現的變數,給定n個形如xi=xjxi=xj的變數相等/不等的約束條件,請判定是否可以分別為每一個變數賦予恰當的值,使得上述所有約束條件同時被滿足。例如,一個問題中的約束條件為:x_1=x_2,x_2=x_3,x_3=x_4,x_4\neq x_1x1=x2,x2=x3,x3=x4,x4=x1,這些約束條件顯然是不可能同時被滿足的,因此這個問題應判定為不可被滿足。

現在給出一些約束滿足問題,請分別對它們進行判定。

輸入格式

輸入的第一行包含一個正整數t,表示需要判定的問題個數。注意這些問題之間是相互獨立的。

對於每個問題,包含若干行:

第一行包含一個正整數n,表示該問題中需要被滿足的約束條件個數。接下來n行,每行包括三個整數i,j,e,描述一個相等/不等的約束條件,相鄰整數之間用單個空格隔開。若e=1,則該約束條件為xi=xj。若e=0,則該約束條件為xi=xj

輸出格式

輸出包括t行。

輸出檔案的第k行輸出一個字串YES或者NO(字母全部大寫),YES表示輸入中的第k個問題判定為可以被滿足,NO表示不可被滿足。

輸入輸出樣例

輸入 #1
2
2
1 2 1
1 2 0
2
1 2 1
2 1 1
輸出 #1
NO
YES
輸入 #2
2
3
1 2 1
2 3 1
3 1 1
4
1 2 1
2 3 1
3 4 1
1 4 0
輸出 #2
YES
NO

說明/提示

注:實際上n10^6。

分析

除開離散化的話算是裸的並查集,寫的時候感覺細節還是蠻多的。 涉及了關於unique在vector的用法

程式碼

//最多隻有2n個數,考慮離散化
//離線操作 

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+5;
int p[N*2
]; vector<int> book;//用於離散化操作 struct Hd { int a; int b; int e; }; Hd hd[N*2]; bool cmp(Hd &n,Hd &m) { return n.e>m.e; }//優先合併操作 int discre(int num)//查詢離散化結果 { return lower_bound(book.begin(),book.end(),num)-book.begin()+1;//+1,vecor從0開始,而p從1開始 } //並查集板子 int getf(int num_a) { if(num_a==p[num_a]) return num_a; else return p[num_a]=getf(p[num_a]); } void mer(int j,int k) { int jf=getf(j); int kf=getf(k); if(jf!=kf) { p[kf]=jf; } } bool my_unique(int j,int k) { return j==k;//定義去重規則 } int main() { int t; cin>>t; while(t--) { memset(p,0,sizeof(p)); book.clear(); int n; cin>>n; for(int i=1;i<=n;i++) { cin>>hd[i].a>>hd[i].b>>hd[i].e; book.push_back(hd[i].a); book.push_back(hd[i].b); } for(int i=1;i<=n*2;i++) { p[i]=i;//細節,並查集要初始化到2n } sort(hd+1,hd+n+1,cmp);//優先合併操作 sort(book.begin(),book.end());//排序 離散表 vector<int>::iterator it; it=unique(book.begin(),book.end(),my_unique);//去重 book.erase(it,book.end()); //vector去重過程 int fl=true; for(int i=1;i<=n;i++) { if(hd[i].e==1) { mer(discre(hd[i].a),discre(hd[i].b)); } else { if(getf(discre(hd[i].a))==getf(discre(hd[i].b))) { fl=false; } } } if(fl==true) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }