UESTC 1586 可以说是非常豹笑了
题意:n个数,m个关系,每个关系表示T==1则a、b两数相同,T == 0则a、b两数不同。
要求判断关系是否没有矛盾。
2-SAT+并查集
有一个大小为2*n的并查集,
如果a、b天相同,则把a和b,以及a+n和b+n,合并,
如果a、b天不同,则把a和b+n,以及a+n和b,合并,
然后i= 1 ~ n,扫一遍,如果 a和a+n在同一颗树中,则相矛盾,
因为不可能那天表情即一样又不一样,答案为NO,
反正为 YES
复杂度 O(2*n)
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 1e6 + 8;
int father[2*MAXN], _rank[2*MAXN];
inline void init(int n)
{
for(int i = 0; i <= n; i++){
father[i] = i;
_rank[i] = 0;
}
}
inline int _find(int x)
{
return father[x] = father[x] == x ? x : _find(father[x]);
}
inline void _merge(int x, int y)
{
int a = _find(x), b = _find(y);
if(a == b) return;
else{
if(_rank[a] < _rank[b]){
father[a] = b;
}
else{
father[b] = a;
if(_rank[a] == _rank[b]){
_rank[a]++;
}
}
}
}
int main()
{
#ifdef LOCAL
freopen("n.txt", "r", stdin);
//freopen("n.out", "w", stdout);
int T = 2;
while(T--){
#endif // LOCAL
//ios::sync_with_stdio(false); cin.tie(0);
int n, m, i, j, t, x, y;
scanf("%d%d", &n, &m);
init(2*n);
for(i = 1; i <= m; i++){
scanf("%d%d%d", &t, &x, &y);
if(t){
_merge(x, y);
_merge(x + n, y + n);
}
else{
_merge(x, y + n);
_merge(x + n, y);
}
}
bool ans = true;
for(i = 1; i <= n; i++){
if(_find(i) == _find(i + n)){
ans = false;
break;
}
}
if(ans) puts("YES");
else puts("NO");
#ifdef LOCAL
cout << endl;
}
#endif // LOCAL
return 0;
}
Thank you!
------from ProLights