題目: |
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