hdu 2489 状态压缩 + 最小生成树

来源:互联网 发布:新疆seo外包 编辑:程序博客网 时间:2024/06/05 21:59
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 16#define M N * Nstruct list{    int v1, v2,w;    bool operator <(const list &b)const{        return  w < b.w;    }}v[M];int top;int weight[N];int ew,nw;int ewg,nwg;int cnt ;int rank[N], fa[N];void MakeSet(int n){    for(int i = 0; i <= n; i++){        rank[fa[i] = i] = 0;    }}int FindSet(int x){    return fa[x]!=x?fa[x]=FindSet(fa[x]):fa[x];}bool Union(int x,int y){    x = FindSet(x); y =FindSet(y);    if(x!=y){        if(rank[x] > rank[y]) fa[y] = x;        else if(rank[x] < rank[y]) fa[x] = y;        else rank[fa[x] = y] ++;                return true;    }    return false;}void kruskal(int n,int m,int x){    int count = 0;    ewg = 0;    for(int i = 0; i < top && count < m -1; i++){        if( ((1<<v[i].v1)&x) && ((1<<v[i].v2)&x)){            if(Union(v[i].v1,v[i].v2)){                ++ count;                ewg += v[i].w;            }        }    }    if(ew * nwg > nw * ewg){        cnt = x;        ew = ewg;        nw = nwg;    }}int work(int n, int m){    for(int i = 1; i <= (1<<n); i++){        int num = 0;        nwg = 0;        for(int  j = 0; j < n; j++){            if(i & (1<<j)){                num ++;                nwg += weight[j];            }        }        if(num == m){            MakeSet(n);            kruskal(n,m,i);        }    }    return cnt;}int main(){//    freopen("in","r",stdin);    int n, m;    while(~scanf("%d%d",&n,&m)&& n + m){        for(int i = 0; i < n; i++){            scanf("%d",&weight[i]);        }        top = 0;        for(int i = 0; i < n; i++){            for(int j = 0; j< n; j++){                int temp;                scanf("%d",&temp);                if(i <= j) continue;                v[top].v1 = i; v[top].v2 = j; v[top].w = temp;                top ++;            }        }        ew = 1500;        nw = 1;        sort(v,v+top);        int x = work(n,m);        int num = 1;        for(int i = 0; i < n; i++){            if((1<<i) & x) {                printf("%d",i+1);                if(num!=m) printf(" ");                num ++ ;            }        }        printf("\n");    }    return 0;}