[Codeforces]160D - Edges in MST

来源:互联网 发布:小米在线软件商店 编辑:程序博客网 时间:2024/05/16 17:36

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]:=edgenumend;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.