poj 1182 食物链

<textarea cols="120" rows="155" name="code" class="cpp">//poj 1182 食物链 并查集应用 /* 此题的重要出发点是动物之间的关系,对每一句话完善关系结构用于判断真假,而不要局限于它们属于A、B还是C类,这个没有意义。 此题如果用向量思想可以精简到一个并查集,每一对明确关系的动物都在同一个并查集里。每一个并查集里的动物都维护一个跟它父 结点的关系,r[a]=0表示同类,r[a]=1表示捕食,r[a]=2表示被捕食,这样就可以得到它跟集合中任何一个元素的关系。 */ #include&lt;iostream&gt; using namespace std; int n,m; int pre[50010],r[50010],rank[50010]; int getr(int a) //获得a与根结点的关系 { int ans=0; while (pre[a]!=a) {ans+=r[a];a=pre[a];} return ans%3; } int find(int a) { if (pre[a]==a) return a; int temp=find(pre[a]); r[a]=(r[a]+r[pre[a]])%3; return pre[a]=temp; } int main() { scanf("%d%d",&amp;n,&amp;m); for (int i=1;i&lt;=n;++i) pre[i]=i; memset(r,0,sizeof(r)); memset(rank,0,sizeof(rank)); int op,a,b,ans=0,ra,rb; while (m--) { scanf("%d%d%d",&amp;op,&amp;a,&amp;b); if (a&gt;n || b&gt;n || op==2 &amp;&amp; a==b) ++ans; //假话2,3 else if ((ra=find(a))==(rb=find(b))){ if ( ((getr(a)-getr(b))%3+3)%3 != op-1) ++ans; //假话1 } else { if ( rank[ra]&lt;rank[rb]) { pre[ra]=rb; r[ra]=((getr(b)+op-1-getr(a))%3+3)%3;} else { pre[rb]=ra; r[rb]=((getr(a)+1-op-getr(b))%3+3)%3; if (rank[ra]==rank[rb]) rank[ra]++; } } } printf("%d/n",ans); system("pause"); return 0; } </textarea>

你可能感兴趣的:(poj 1182 食物链)