通讯
题目大意
HHJJYY
特工组织共有
N
个部门(总部编号为0),通讯网络有
现在要从总部通过通讯线路发布一条
HHZZJJ
怪兽入侵重要据点的紧急信息,要求所有部门都要收到信息且总费用为所有被使用了的线路的费用和。
另外,如果两个部门可以直接或间接地相互传递消息(即能将信息由X传递到Y,同时能由Y传递到X),我们就可以忽略它们之间的花费。(数据保证所有部门都能传递到信息)
求最小花费。
数据范围
题解
首先,用Tarjan算法求出所有强连通分量,同一个强连通分量里的点传递信息不需要费用,因此我们可以把同个强连通分量里的点缩成一个点,新缩成的点拥有原强连通分量里的点所拥有的边。
新生成的图便是DAG(有向无环图)。
因为所有的部门都能被传递到信息,对于某个点
i
,以
对于每个点(包括新生成的点)都进行一次上述操作并统计费用即可。
Code(Pascal)
var
gs,dfn,low,zh,co,en:array[0..100000] of longint;
ss,s:array[0..60000] of boolean;
bj:array[0..100000,1..3] of longint;
n,m,j,k,l,i,o,top,height,cc:longint;
ans:int64;
function min(a,b:longint):longint;
begin
if a<b then exit(a)
else exit(b);
end;
procedure qsort(l,r:longint);
var
i,j,m:longint;
begin
i:=l;
j:=r;
m:=bj[(l+r) div 2,1];
repeat
while bj[i,1]<m do inc(i);
while bj[j,1]>m do dec(j);
if i<=j then
begin
bj[0]:=bj[i];
bj[i]:=bj[j];
bj[j]:=bj[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
procedure tarjan(o:longint);
var
i:longint;
begin
inc(height);
dfn[o]:=height;
low[o]:=height;
inc(top);
zh[top]:=o;
ss[o]:=true;
s[o]:=true;
for i:=en[o-1]+1 to en[o] do
if not(s[bj[i,2]]) then
begin
tarjan(bj[i,2]);
low[o]:=min(low[o],low[bj[i,2]]);
end else
if ss[bj[i,2]] then low[o]:=min(low[o],dfn[bj[i,2]]);
if dfn[o]=low[o] then
begin
inc(k);
cc:=0;
while zh[top+1]<>o do
begin
ss[zh[top]]:=false;
gs[zh[top]]:=k;
inc(cc);
dec(top);
end;
if cc=1 then
begin
gs[o]:=o;
dec(k);
end;
end;
end;
begin
readln(n,m);
if (n=0) and (m=0) then break;
k:=n;
for i:=1 to m do
begin
readln(bj[i,1],bj[i,2],bj[i,3]);
inc(bj[i,1]);
inc(bj[i,2]);
inc(en[bj[i,1]]);
end;
qsort(1,m);
for i:=2 to n do
en[i]:=en[i-1]+en[i];
top:=0;
height:=0;
tarjan(1);
ans:=0;
for i:=1 to k do
co[i]:=maxlongint-10;
for i:=1 to m do
if gs[bj[i,1]]<>gs[bj[i,2]] then
co[gs[bj[i,2]]]:=min(co[gs[bj[i,2]]],bj[i,3]);
co[gs[1]]:=0;
for i:=2 to n do
if (gs[i]=i) then ans:=ans+co[i];
for i:=n+1 to k do
ans:=ans+co[i];
writeln(ans);
end.