【NOI2000/codevs1074/tyvj1438】食物链 解题报告
100 7
1 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
3
自己调+听老师讲+看题解+写代码==AC;
虐爆了我的并查集的自信心的题。。。。
看的题解是虚点+并查集,然而现在还并不知道虚点是什么东西。。。。求神犇指教、、、
不过题解的思路是看懂了的。。
1~n为n种动物的同类集合,n+1~n+n为这种动物的天敌集合,n*2+1~3*n为这种动物的食物集合;
如果D==1:判断假话的方法为:X的食物集合里有Y,或Y的食物集合里有X,或X的天敌集合里有Y,或Y的天敌集合里有X;合并的方法为:X的同类集合与Y的同类集合合并,X的天敌集合与Y的天敌集合合并,X的食物集合与Y的食物集合合并;
如果D==2:判断假话的方法为:X的天敌集合里有Y,或Y的食物集合里有X;合并的方法为:X与Y的天敌集合合并,Y与X的食物集合合并,X的天敌集合与Y的食物集合合并(由题意可知,如果Z是X的天敌,Y是X的食物,那么Z是Y的食物);
【代码】
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=350005; int n,m,i,ans,a1,b1,c1,maxp; int fa[MAXN]; int findf(int x) { if (fa[x]==x) return x; return fa[x]=findf(fa[x]); } void unions(int x,int y) { if (findf(x)!=findf(y)) fa[fa[x]]=fa[y]; return; } int main() { scanf("%d%d",&n,&m); maxp=3*n; for (i=1;i<=maxp;++i) fa[i]=i; for (i=1;i<=m;++i) { scanf("%d%d%d",&a1,&b1,&c1); if (b1>n||c1>n||b1==c1&&a1==2) { ans++; continue; } if (a1==1) { if (findf(b1)==findf(n+c1)||findf(b1)==findf(n*2+c1)||findf(n+b1)==findf(c1)||findf(n*2+b1)==findf(c1)) { ++ans; continue; } unions(b1,c1); unions(n+b1,n+c1); unions(n*2+b1,n*2+c1); } if (a1==2) { if (findf(b1)==findf(c1)||findf(b1)==findf(n+c1)||findf(n*2+b1)==findf(c1)) { ++ans; continue; } unions(b1,n*2+c1); unions(n+b1,c1); unions(n*2+b1,n+c1); } } printf("%d\n",ans); return 0; }