1. 程式人生 > >[帶權並差集] Jzoj P1503 體育場

[帶權並差集] Jzoj P1503 體育場

現在 png pan namespace str main find mat fix

Description

  觀眾席每一行構成一個圓形,每個圓形由300個座位組成,對300個座位按照順時針編號1到300,且可以認為有無數多行。現在比賽的組織者希望觀眾進入場地的順序可以更加的有趣,在門票上並沒有規定每個人的座位,而是與這個圈中某個人的相對位置,可以坐在任意一行。
  門票上標示的形式如下:A B x 表示第B個人必須在A的順時針方向x個位置(比如A坐在4號位子,x=2,則B必須坐在6號位子)。
  現在你就座位誌願者在入場口檢票。如果拿到一張門票,與之前給定的矛盾,則被視為是假票,如果無矛盾,視為真票。現在給定該行入場觀眾的順序,以及他們手中的門票,請問其中有多少假票?

Input

  第一行兩個數n(1<=n<=50,000)和m(1<=m<=100,000)。n表示人數。
  接下來m行,每行三個數A,B,x標示B必須坐在A的順時針方向x個位置。(1<=A<=N), B(1<=B<=N), X(0<=X<300) (A!=B)
  以上字母含義如題所述。

Output

  僅一個數,表示在m張票中有多少假票。

Sample Input

10 10
1 2 150
3 4 200
1 5 270
2 6 200
6 5 80
4 7 150
8 9 100
4 8 50
1 7 100
9 2 100

Sample Output

2

Hint

【樣例解釋】
  第5張和第10張是假票
【數據範圍】
  對於20%的數據:n<=100
  對於100%的數據:n<=50,000。

題解

  • 設dis[i]為i與它父親的距離,fa[i]表示它的父親,讀人的距離為c
  • 當fa[a]==fa[b]時
  • 在合法情況下:dis[a]+c=dis[b]
  • 技術分享圖片
  • 在a和b不同父親時
  • 技術分享圖片
  • 合法情況下:fa[a]與fa[b]的距離d=dis[a]-dis[b]+c

代碼

 1 #include<cstdio> 
 2 #include<iostream>
 3
#include<algorithm> 4 #include<cmath> 5 using namespace std; 6 int n,m,fa[600010],dis[600010],x,y,z,a,b,ans; 7 int find(int x) 8 { 9 if (x==fa[x]) return x; 10 int k=fa[x]; 11 fa[x]=find(fa[x]); 12 dis[x]=(dis[x]+dis[k])%300; 13 return (fa[x]); 14 } 15 void insert(int x,int y,int z) 16 { 17 int u=find(x),v=find(y); 18 fa[v]=u; 19 dis[v]=(dis[x]-dis[y]+z+300)%300; 20 } 21 int main() 22 { 23 scanf("%d%d",&n,&m); 24 for (int i=1;i<=n;i++) fa[i]=i; 25 for (int i=1;i<=m;i++) 26 { 27 scanf("%d%d%d",&x,&y,&z); 28 int u=find(x),v=find(y); 29 if (u!=v) insert(x,y,z); 30 else if ((dis[x]+z)%300!=dis[y]) ans++; 31 } 32 printf("%d\n",ans); 33 return 0; 34 }

[帶權並差集] Jzoj P1503 體育場