正解
这道题类似于 食物链,但比这道题简单。
我们可以维护一个有 (2n) 个节点的并查集,理解时分成两个区间 ([1,n],[n+1,2n])。每个区间的对应值((i) 与 (n+i))属于一种对立关系,一真一假,排好可能的正反两种情况。所以这两个数不能属于同一连通块。
接下来就很简单了。我们在它输入时同时进行处理、判断。当两个对应点属于同一个连通块时,那肯定不行,跳出。
代码
#include<bits/stdc++.h>
using namespace std;
int f[2005];
int getf(int k) {
if(f[k]==k) {
return k;
}
return f[k]=getf(f[k]);
}
void merge(int u,int v) {
u=getf(u),v=getf(v);
if(u!=v) {
f[u]=v;
}
}
int main() {
int n,m;
scanf("%d %d",&n,&m);
for(int i=1; i<=n*2; i++) {
f[i]=i;
}
for(int k=1; k<=m; k++) {
int x,y;
char c[3];
scanf("%d %d %s",&x,&y,c);
if(!strcmp(c,"T")) {
merge(x,y),merge(x+n,y+n);
} else {
merge(x,y+n),merge(x+n,y);
}
for(int i=1; i<=n; i++) {
if(getf(i)==getf(i+n)) {
printf("%d",k-1);
return 0;
}
}
}
printf("%d",m);
return 0;
}
后记
-
如果代码一直有问题时,在很清楚的知道这道题的知识点、方向、思路正确的前提下,并且代码实现并不复杂,可以考虑重写代码,说不定有惊喜~
-
如果有相似模块需要更改后重新调用,在空间充裕的前提下可以采用命名空间(namespace)来规避名字污染、初始化不到位等情况。
-
如果要输入字符,建议以输入字符串的形式进行。