题目链接
https://www.luogu.org/problemnew/show/P1955
题解
毫无悬念,这是一道签到题。
如果把所有变量看作一个点,那么相等关系就是在这两个点之间连一条边,而不等关系不与相等关系矛盾的必要条件则是:两个点不能处在同一集合中。
于是我们可以用并查集来维护这样的一个系统:如果给出一个相等关系,就合并两个集合,将所有的不等关系存储起来,在最后处理不等关系,如果两个点处于同一集合,那么这样的不等关系就不能满足。
PS:由于变量下标的范围达到了10^9,所以可以运用hash(map?)将下标映射到1-2*10^5的范围以内再进行处理。
1 #include <cstdio> 2 #include <algorithm> 3 #include <map> 4 #include <cstring> 5 using namespace std; 6 map<int,int> num; 7 int fa[200005]; 8 int tj[100005][2]; 9 int find(int a)//用递归写会爆栈,所以这里用非递归写了 10 { 11 int r=a; 12 while(r!=fa[r]) 13 r=fa[r]; 14 int i=a,j; 15 while(i!=r) 16 { 17 j=fa[r]; 18 fa[i]=r; 19 i=j; 20 } 21 return r; 22 } 23 void unionn(int i,int j) 24 { 25 fa[j]=i; 26 } 27 void setfa() 28 { 29 for(int i=1;i<=200000;i++) 30 fa[i]=i; 31 } 32 int main() 33 { 34 int t; 35 scanf("%d",&t); 36 while(t--) 37 { 38 int cnt=0,cntt=0; 39 num.clear(); 40 memset(tj,0,sizeof(tj)); 41 setfa(); 42 int n; 43 scanf("%d",&n); 44 for(int k=1;k<=n;k++) 45 { 46 int i,j,e; 47 scanf("%d%d%d",&i,&j,&e); 48 if(num[i]==0)num[i]=++cnt;//map大法好,但常数确实大了 49 if(num[j]==0)num[j]=++cnt;//可以试试unordered_map? 50 if(e)unionn(find(num[i]),find(num[j])); 51 else 52 { 53 cntt++; 54 tj[cntt][0]=num[i]; 55 tj[cntt][1]=num[j]; 56 } 57 } 58 int flag=1; 59 for(int i=1;i<=cntt;i++) 60 if(find(tj[i][0])==find(tj[i][1])) 61 { 62 puts("NO"); 63 flag=0; 64 break; 65 } 66 if(flag)puts("YES"); 67 } 68 return 0; 69 }