CF 160D Edges in MST 最小生成树的性质,寻桥,缩点,批量处理 难度:3

http://codeforces.com/problemset/problem/160/D

这道题要求哪条边存在于某个最小生成树中,哪条边不存在于最小生成树中,哪条边绝对存在于最小生成树中

明显桥边一定存在于所有最小生成树中,然而怎么处理存在某个最小生成树的边呢?

借助kruskal算法的性质,由小到大,每次处理同一权值的边,如果边连接的点已经联通就不要管,否则那些处理的边一定存在于某最小生成树上

批量处理的思想很巧妙

#include <cstdio>

#include <vector>

#include <stack>

#include <algorithm>

using namespace std;

const int maxn=2e5+5;

int first[maxn];

struct edge{

        int t,ind,nxt;

}e[maxn];

int from[maxn],to[maxn],cost[maxn],index[maxn];

int sta[maxn];

int n,m,len;



void addedge(int f,int t,int ind,int i){

        e[i].nxt=first[f];

        first[f]=i;

        e[i].t=t;

        e[i].ind=ind;

}

int par[maxn],num[maxn];

int fnd(int x){return par[x]==x?x:par[x]=fnd(par[x]);}

void unit(int a,int b){

        if(fnd(a)==fnd(b))return;

        num[fnd(b)]+=num[fnd(a)];

        num[fnd(a)]=0;

        par[fnd(a)]=fnd(b);

}

bool cmp(int a,int b) {return cost[a]<cost[b];}



int dfn[maxn],low[maxn],cnt;

void dfs(int s,int f){

        dfn[s]=low[s]=++cnt;

        for(int p=first[s];p!=0;p=e[p].nxt){

                int t=e[p].t;

                if(p==(((f-1)^1)+1))continue;

                if(dfn[t]==0){

                        dfs(t,p);

                        if(low[t]>dfn[s]){

                                sta[e[p].ind]=2;

                        }

                        else{

                                low[s]=min(low[s],low[t]);

                        }

                }

                else {

                        low[s]=min(low[s],dfn[t]);

                }

        }

}



int st[maxn],tail;

void kruskal2(){

        sort(index,index+m,cmp);

        for(int i=0;i<m&&num[fnd(1)]<n;){

                int j=i;

                while(cost[index[i]]==cost[index[j]]&&j<m){j++;}

                for(int k=i;k<j;k++){

                        int indk=index[k];

                        if(fnd(from[indk])!=fnd(to[indk])){

                                st[tail++]=indk;

                                sta[indk]=1;

                        }

                }

                for(int p=0;p<tail;p++){

                        int tp=st[p];

                        int f=fnd(from[tp]),t=fnd(to[tp]);

                        addedge(f,t,tp,++len);

                        addedge(t,f,tp,++len);

                }

                for(int p=0;p<tail;p++){

                        int tp=st[p];

                        int f=fnd(from[tp]),t=fnd(to[tp]);

                        dfs(f,0);

                        unit(f,t);

                }

                cnt=0;

                len=0;

                for(int p=0;p<tail;p++){

                        int tp=st[p];

                        int f=fnd(from[tp]),t=fnd(to[tp]);

                        first[f]=first[t]=0;

                        dfn[f]=dfn[t]=0;

                }



                i=j;

                tail=0;

        }

}





int main(){

        scanf("%d%d",&n,&m);

        for(int i=1;i<=n;i++){par[i]=i;num[i]=1;}



        for(int i=0;i<m;i++){

                scanf("%d%d%d",from+i,to+i,cost+i);

                index[i]=i;

        }

        kruskal2();





        for(int i=0;i<m;i++){

                if(sta[i]==2)puts("any");

                else if(sta[i]==1)puts("at least one");

                else puts("none");

        }

        return 0;

}

  

你可能感兴趣的:(最小生成树)