Clarke and MST HDU - 5627

http://acm.hdu.edu.cn/showproblem.php?pid=5627

要求一棵且运算结果最大的SPT 肯定不能简单按权值排序

贪心考虑 枚举二进制位 如果2^i可以被满足 完全可以牺牲掉2^(i-1) 2^(i-2)...

枚举到2^i时 从目前所有边中找出边权的二进制位中i位为1的边 看能否将图连通 能的话就把低位的范围限定在所有边权的二进制位中i位为1的边中 若不连通则放弃2^i 转而在当前所有边中凑2^(i-1)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=3e5+10;

struct node
{
    int u,v,w;
};

node edge[maxn];
int f[maxn],book[maxn];
int pre[50];
int n,m;

void init()
{
    int i;
    pre[0]=1;
    for(i=1;i<=29;i++){
        pre[i]=2*pre[i-1];
    }
}

int getf(int p)
{
    if(f[p]==p) return p;
    else return f[p]=getf(f[p]);
}

void unite(int u,int v)
{
    int fu,fv;
    fu=getf(u),fv=getf(v);
    if(fu!=fv){
        f[fv]=fu;
    }
}

int main()
{
    int t,i,j,ans,cnt;
    init();
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(i=1;i<=m;i++){
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        memset(book,0,sizeof(book));
        ans=0;
        for(j=29;j>=0;j--){
            for(i=1;i<=n;i++) f[i]=i;
            for(i=1;i<=m;i++){
                if(!book[i]&&(edge[i].w&(1<<j))){
                    unite(edge[i].u,edge[i].v);
                }
            }
            cnt=0;
            for(i=1;i<=n;i++){
                if(f[i]==i) cnt++;
            }
            if(cnt==1){
                for(i=1;i<=m;i++){
                    if(!book[i]&&(edge[i].w&(1<<j))){
                        book[i]=1;
                    }
                }
                ans+=(1<<j);
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/88851687
MST