不想多說什麼了,這題虐我不淺,還是看完別人的解題報告的情況下。
#include<iostream>#include<cstdio>#include<cstring>using namespace std;int father[50001],relative[100001];int n;int find_ant(int c){if(father[c]!=c){int t=find_ant(father[c]); //這一句和下一句不能顛倒,relative[]必須出現在find_ant()後,也就是說relative[]是在遞迴的回溯過程中建立的,這樣才能保證relative[]對應的祖先節點是正確的。只有在祖先節點確定的情況才能計算relative[]。而relative[]出現在find_ant()前面時,先建立了relative[]和當前的祖先節點(並非最終確定的祖先節點),隨後祖先節點又在遞迴中被改變,relative[]就不正確了。羅嗦了大半天,就一句,relative[]的建立一定出現在find_ant()之後。relative[c]=(relative[c]+relative[father[c]])%3;father[c]=t;}return father[c];}bool _union(int x,int y,int r){ int px=find_ant(x); int py=find_ant(y); if(x>n||y>n) return true; if(px==py){ if(relative[x]==relative[y]&&r==1) return false; if((relative[x]-relative[y]+3)%3==2&&r==2) return false; return true; } relative[py]=(3-relative[y]+r-1+relative[x])%3; father[py]=px; return false;}int main(){ int k; int i; int x,y,g; int res=0; scanf("%d%d",&n,&k);for(i=1;i<=n;i++){ father[i]=i;relative[i]=0;} while(k--){ scanf("%d%d%d",&g,&x,&y); if(_union(x,y,g)) res++; }printf("%d\n",res); return 0;}