uvaLive6837 ThereIsNoAlternative (kruskal)
题意:给一个联通图,求出不可替代的边,即存在于所有最小生成树中的边,的数量和它们边权之和
首先kruskal跑出一个最小生成树,枚举其中所有的边,若把这条边去掉以后再跑kruskal答案不是最小,则这条边就是不可替代的
复杂度:O(MlogM+N*N)
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxN=550,maxM=55000; typedef struct{ int a,b,l; } Edge; int bcj[maxN]; int n,m; Edge eg[maxM]; int ts[maxN]; bool cmp(Edge a,Edge b){ return a.l<b.l; } int getf(int i){ return i==bcj[i]?i:(bcj[i]=getf(bcj[i])); } void add(int a,int b){ bcj[getf(a)]=getf(b); } int OPRATE(int rmvd){ int i,j,num=0,re=0; for(i=1;i<=n;i++) bcj[i]=i; i=0; while(num<n-1){ if(i!=rmvd && getf(eg[i].a)!=getf(eg[i].b)){ add(eg[i].a,eg[i].b); re+=eg[i].l; if(rmvd==-1) ts[num]=i; num++; } i++; if(i>=m && num<n-1) return -1; } return re; } int main(){ int i,j,ansn,answ,min; while(scanf("%d%d",&n,&m)==2){ for(i=0;i<m;i++){ scanf("%d%d%d",&eg[i].a,&eg[i].b,&eg[i].l); } sort(eg,eg+m,cmp); min=OPRATE(-1); ansn=n-1;answ=min; for(i=0;i<n-1;i++){ if(OPRATE(ts[i])==min){ ansn--; answ-=eg[ts[i]].l; } } printf("%d %d\n",ansn,answ); } }