题目链接:点击这里
题意:
输入 表示有一个长度为 的 字符串, 表示接下来有 行输入,接下来的 行输入中 表示第 到第 个字符中间 的个数为偶数个; 表示第 到第 个字符中间 的个数为奇数个。若 句话中第 是第一次与前面的话矛盾,则输出 。
思路分析:
表示 是偶数这一条件, 表示 是奇数这一条件
是同类
- 如果 是奇数,那么 是奇数
- 如果 是偶数,那么 是偶数
是异类
- 如果 是偶数,那么 是奇数
- 如果 是奇数,那么 是偶数
理解:
边带权的并查集: 与 是有关系的,它们就在同一个集合,至于关系是什么就要看权值是多少
扩展域的并查集:集合里只要有一个条件成立,那么其余所有条件必然成立。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N = 40010, base = N / 2;
int n, m;
int p[N];
map<int,int> mp;
int get(int x) // 在线离散化
{
if(mp.count(x) == 0) mp[x] = ++n;
return mp[x];
}
int find(int x)
{
if(x != p[x]) p[x] = find(p[x]);
return p[x];
}
int main()
{
scanf("%d%d", &n, &m);
n = 0; // 用于离散化
for(int i = 1; i < N; ++i) p[i] = i; // 初始化
int res = m;
for(int i = 1; i <= m; ++i)
{
int a, b;
char op[6];
scanf("%d%d%s", &a, &b, op);
if(res != m) continue;
a = get(a - 1), b = get(b);
if(op[0] == 'e') // 同类
{
if(find(a + base) == find(b)) // 有矛盾
{
res = i - 1;
break; // 数据没有输入完,可以break
}
p[find(a)] = find(b);
p[find(a + base)] = find(b + base);
}
else // 异类
{
if(find(a) == find(b)) // 有矛盾
{
res = i - 1;
break;
}
p[find(a)] = find(b + base);
p[find(a + base)] = find(b);
}
}
printf("%d\n", res);
return 0;
}