卧薪尝胆,厚积薄发。
NOI2015 程序自动分析
Date: Sat Sep 15 16:39:57 CST 2018 In Category: NoCategory

Description:

给出一些变量的等于和不等于关系,判断是否合法。
$1\le n \le 100000$

Solution:

先把所有询问存起来离散化,把所有等于的关系用并查集合并,最后依次判断不等的两个是否在不同集合。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<map>
#include<vector>
#include<cstring>
using namespace std;
inline int read()
{
register int res = 0;
register char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res;
}
int n;
#define MAXN 100010
int f[MAXN << 1];
int find(int x){return (f[x] == x ? x : f[x] = find(f[x]));}
struct lin{int u,v,w;};
vector<lin> g;
map<int,int> fr;
int to[MAXN << 1],tot = 0;
int s[MAXN << 1];
void work()
{
scanf("%d",&n);
for(int i = 1;i <= 2 * n;++i)f[i] = i;
int a,b,c;g.clear();
for(int i = 1;i <= n;++i)
{
a = read();b = read();c = read();
g.push_back((lin){a,b,c});
s[2 * i - 1] = a;s[2 * i] = b;
}
sort(s + 1,s + 1 + 2 * n);
fr.clear();tot = 0;
memset(to,0,sizeof(to));
for(int i = 1;i <= 2 * n;++i)
{
if(i == 1 || s[i] != s[i - 1])
{
fr[s[i]] = ++tot;
to[tot] = s[i];
}
}
for(vector<lin>::iterator i = g.begin();i != g.end();++i)
{
if(i -> w == 1)
{
if(find(fr[i -> u]) == find(fr[i -> v]))continue;
f[find(fr[i -> u])] = find(fr[i -> v]);
}
}
for(vector<lin>::iterator i = g.begin();i != g.end();++i)
{
if(i -> w == 0)
{
if(find(fr[i -> u]) == find(fr[i -> v]))
{
puts("NO");
return;
}
}
}
puts("YES");
return;
}
int main()
{
int testcases = read();
while(testcases--)work();
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡