Analysis
这道题的大意是在一个无向图中,任意构造一棵最小生成树,求有哪一些边一定出现,哪一些边有可能出现,哪一些边一定不会出现。英语太渣了不敢在Codeforces上写题解(而且那里已经有很好的题解了),就在这里自己理一下思路吧。把所有边按权值由小到大排序,像Kruskal这样做过来,但是权值相同的边要一起做(有一个结论,设T是图G的一棵最小生成树,L是T中各边权值的一个已排序的列表,那么对于G的任何其他最小生成树T',L也是T'中各边权值的一个已排序的列表,参见《算法导论》P347练习23.1-8),那么在这些权值两两相同的边中属于最小生成树的边数是确定的。如果其中某一条边连接的是在添加这些边之前就已连通的点,那么这条边肯定不会存在于最小生成树中,如果添加了这些边后某一条边是割边,那么这条边一定存在于所有的最小生成树中。剩下的边都是有可能存在于最小生成树中。那么用并查集+dfs求割边即可。
Accepted Code
type
edge=record
a,b,w,lab:longint;
end;
edge2=record
dt,lab,next:longint;
end;
var
e:array[0..100100] of edge;
g:array[0..200200] of edge2;
first,dfn,lowlink,ans,f,fa:array[0..100100] of longint;
i,n,m,t1,t2,sign,now,last,num,edgenum:longint;
procedure sort(l,r:longint);
var
i,j,mid:longint;
tmp:edge;
begin
i:=l;
j:=r;
mid:=e[(l+r+r) div 3].w;
repeat
while e[i].w<mid do
inc(i);
while mid<e[j].w do
dec(j);
if not (i>j) then
begin
tmp:=e[i];
e[i]:=e[j];
e[j]:=tmp;
inc(i);
dec(j);
end;
until i>j;
if i<r then
sort(i,r);
if l<j then
sort(l,j);
end;
procedure addedge(u,v,i:longint);
begin
inc(edgenum);
g[edgenum].dt:=v;
g[edgenum].lab:=e[i].lab;
g[edgenum].next:=first[u];
first[u]:=edgenum
end;
procedure dfs(u:longint);
var
v,t:longint;
begin
inc(sign);
dfn[u]:=sign;
lowlink[u]:=sign;
t:=first[u];
while t<>0 do
begin
v:=g[t].dt;
if g[t].lab<>f[u] then
begin
if dfn[v]=0 then
begin
f[v]:=g[t].lab;
dfs(v);
if lowlink[v]<lowlink[u] then
lowlink[u]:=lowlink[v];
if lowlink[v]>dfn[u] then
ans[g[t].lab]:=1;
end
else
if lowlink[u]>dfn[v] then
lowlink[u]:=dfn[v];
end;
t:=g[t].next;
end;
end;
function getfa(t:longint):longint;
begin
if fa[t]<>t then
fa[t]:=getfa(fa[t]);
getfa:=fa[t];
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(e[i].a,e[i].b,e[i].w);
e[i].lab:=i;
end;
sort(1,m);
for i:=1 to n do
fa[i]:=i;
now:=1;
num:=0;
repeat
last:=now;
while (last+1<=m) and (e[last].w=e[last+1].w) do
inc(last);
edgenum:=0;
for i:=now to last do
begin
t1:=getfa(e[i].a);
t2:=getfa(e[i].b);
if t1=t2 then
ans[e[i].lab]:=-1
else
begin
first[t1]:=0;
first[t2]:=0;
dfn[t1]:=0;
dfn[t2]:=0;
end;
end;
sign:=0;
edgenum:=0;
for i:=now to last do
if ans[e[i].lab]<>-1 then
begin
t1:=getfa(e[i].a);
t2:=getfa(e[i].b);
addedge(t1,t2,i);
addedge(t2,t1,i);
end;
for i:=now to last do
begin
t1:=getfa(e[i].a);
t2:=getfa(e[i].b);
if t1<>t2 then
begin
fa[t2]:=t1;
inc(num);
end;
end;
for i:=now to last do
if (ans[e[i].lab]<>-1) then
begin
t1:=getfa(e[i].a);
if dfn[t1]=0 then
dfs(t1);
end;
now:=last+1;
if num=n-1 then
begin
for i:=now to m do
ans[e[i].lab]:=-1;
now:=m+1;
end;
until now>m;
for i:=1 to m do
case ans[i] of
-1:writeln('none');
0:writeln('at least one');
1:writeln('any');
end;
end.