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;}