poj 1182--食物链 (并查集)
题目链接:https://vjudge.net/contest/220024#problem/E
题目没大意(中文题,哪里还用得到大意)
在原始的基础上,需要考虑到三者的关系维护,还有就是千万不要用C++的输入输出流读取,因为数据量大,时间上会超限
维护的时候首先要考虑反情况(范围外,吃与被吃的关系),如果不存在反情况的话,那么就可以认为这种情况是正确的,
那接下来的做法就是把正确的情况更新一下,吃,被吃和同类的三个关系同时更新一下;如果存在反情况的话,就把定义储
存反情况的数目更新一下即可, 不废话了,还是看代码吧。
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> using namespace std; #define MAX_N 51000 int f[4 * MAX_N]; int n, k; int d, x, y; int geft(int x) { while(x != f[x]) x = f[x]; return x; } void finds(int u, int v) { f[geft(v)] = geft(u); } ///f[x]储存同类 f[x+n]储存吃x的 f[x+2*n]储存被x吃的 bool pan1(int x,int y)/// 判断x和y是同类是不是真话? { if(x<=0 || x>n || y<=0 || y>n) return false; if(geft(y) == geft(x+n)) return false; if(geft(y) == geft(x+2*n)) return false; return true; } bool pan2(int x,int y)/// 判断x吃y是不是真话? { if(x<=0 || x>n || y<=0 || y>n) return false; if(geft(x) == geft(y)) return false; if(geft(y) == geft(x+2*n)) return false; return true; } int main() { int i, j; int ans = 0; scanf("%d%d", &n, &k); for(i=1;i<=4*n;i++) f[i] = i; for(i=0; i<k; i++) { scanf("%d%d%d", &d, &x, &y); if(x<=0 || x>n || y<=0 || y>n) { ans++; continue; } if(d == 1)///判断是不是同类 { if(pan1(x, y)) { finds(x, y); finds(x+n, y+n); finds(x+2*n, y+2*n); } else ans++; } else { if(pan2(x,y)) { finds(x+n, y); finds(x, y+2*n); finds(y+n,x+2*n); } else ans++; } } cout<<ans<<endl; return 0; }
(说不采用C++的输入输出流,还是在不时间超限的基础上,用上了输出的方式,没办法,挺方便的,就是耗时长了一点)