Pku 2832 How Many Pairs?

題目:

 How Many Pairs?

來源:

 Pku 2832

題目大意:

 題意讓我理解了半天,果然英語不好。

 其實就是n個點m條邊q次訪問,每次輸出任何一對點只要其所經過的邊的最長邊比  訪問值小就行的有效點數量

數據範圍:

 1 < N ≤ 10,000, 0 < M ≤ 50,000, 0 < Q ≤ 10,000

樣例:

 4 5 4
 1 2 1
 2 3 2
 2 3 5
 3 4 3
 4 1 4
 0
 1
 3
 2
0
1
6
3
 

做題思路:

 如果題意看懂了貌似就不那麼難了,寫的是類似kruskal的,所以就那麼叫了。先把  訪問值和邊按從小到大排了,然後並查集合並,合併時注意減去重複的

知識點:

 並查集、kruskal

type
 act=record
 x,y,d:longint;
 end;
 atp=array[0..50000]of longint;
var
 a:array[0..50010]of act;
 ans,time,tot,b,f:array[0..50000]of longint;
 n,i,q,m,x,y,d:longint;
procedure qsorta(l,r:longint);
var
 i,j,k:longint;
 t:act;
begin
 i:=l;j:=r;
 k:=a[(l+r)shr 1].d;
 repeat
  whilea[i].d<k do inc(i);
  whilea[j].d>k do dec(j);
  ifi<=j then
  begin
   t:=a[i];a[i]:=a[j];a[j]:=t;
   inc(i);dec(j);
   end;
 untili>j;
 ifi<r then qsorta(i,r);
 ifj>l then qsorta(l,j);
end;
procedure qsortb(l,r:longint;vart:atp);{<t數組是形變參。。。>}
var
 tmp,i,j,k:longint;
begin
 i:=l;j:=r;
 k:=t[(l+r)shr 1];
 repeat
  whilet[i]<k do inc(i);
  whilet[j]>k do dec(j);
  ifi<=j then
  begin
   tmp:=t[i];t[i]:=t[j];t[j]:=tmp;
   tmp:=time[i];time[i]:=time[j];time[j]:=tmp;
   inc(i);dec(j);
   end;
 untili>j;
 ifi<r then qsortb(i,r,t);
 ifj>l then qsortb(l,j,t);
end;
function getf(x:longint):longint;
begin
 iff[x]=x then exit(x);
 f[x]:=getf(f[x]);
 exit(f[x]);
end;
procedure union(x,y:longint);
begin
 f[x]:=y;
end;
procedure kruskal;{<好像kruskal所以就這麼命名啦>}
var
 i,j,last,x,y:longint;
begin
 fori:=1 to n do
  begin
  f[i]:=i;
  tot[i]:=1;{<初始化對應點>}
  end;
 fillchar(ans,sizeof(ans),0);
 last:=1;
 fori:=1 to q do
  begin
  ans[time[i]]:=ans[time[i-1]];{<訪問值再time下是越來越大的,所以可以先把之前求出來的賦給要求的>}
   forj:=last to m do
   begin
     ifa[j].d>b[i] then{<由於對邊排序了,所以第一個大於訪問值的就是第一個大於的>}
     begin
      last:=j;
      break;
     end;
  x:=getf(a[j].x);y:=getf(a[j].y);
   ifx<>y then
   begin
    union(x,y);
    ans[time[i]]:=ans[time[i]]-tot[x]*(tot[x]-1) div 2-tot[y]*(tot[y]-1) div2;{<累計答案是要注意不要讓對應點重複了,所以先減後加>}
    tot[y]:=tot[x]+tot[y];
    ans[time[i]]:=ans[time[i]]+tot[y]*(tot[y]-1)div 2;
   end;
  end;
 end;
end;
begin
 readln(n,m,q);
 fori:=1 to m do
  begin
   witha[i] do{<記錄性特有滴。。>}
  readln(x,y,d);
  end;
 fori:=1 to q do
  begin
  time[i]:=i;{<排序就不動原數了,以免輸出時麻煩,所以把序號排了>}
  readln(b[i]);
  end;
 qsorta(1,m);
 qsortb(1,q,b);
 kruskal;
 fori:=1 to q do writeln(ans[i]);
end.
題目來源:http://poj.org/problem?id=2832

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章