Minimal Ratio Tree HDU - 2489
考察:最小生成树+枚举
错误思路:
枚举m个点,将m个点的边权值计入和,与点权值和作商求最小值
上面的思路错在题目是要求求m个点的树的比率最小.如果边权值不去掉一个而全部计入的话就会WA
正确思路:
枚举m个点,求最小生成树
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 const int N = 20,Max = 0x3f3f3f3f; 6 int node[N],m,n,g[N][N],path[N],cnt,p[N]; 7 double ans; 8 bool vis[N]; 9 vector<int> v; 10 struct Edge{ 11 int u,v,w; 12 bool operator<(Edge x){ 13 return this->w<x.w; 14 } 15 }edge[N*N]; 16 int findf(int x) 17 { 18 if(x!=p[x]) p[x] = findf(p[x]); 19 return p[x]; 20 } 21 void dfs(int k,int st,double sum) 22 { 23 if(k==m){ 24 cnt = 0; 25 for(int i=1;i<=n;i++) p[i] = i; 26 for(int i=0;i<k;i++) 27 for(int j=i+1;j<k;j++) 28 edge[++cnt] = {path[i],path[j],g[path[i]][path[j]]}; 29 sort(edge+1,edge+cnt+1); 30 double esum = 0; 31 for(int i=1;i<=cnt;i++){ 32 int x = findf(edge[i].u), y = findf(edge[i].v); 33 if(x!=y){ 34 p[x] = y; 35 esum+=edge[i].w; 36 } 37 } 38 if(esum/sum<ans){ 39 ans = esum/sum; 40 v.clear(); 41 for(int i=0;i<k;i++) v.push_back(path[i]); 42 } 43 return; 44 } 45 for(int i=st;i<=n;i++){ 46 if(!vis[i]) 47 { 48 vis[i] = 1; 49 path[k] = i; 50 dfs(k+1,i+1,sum+node[i]); 51 vis[i] = 0; 52 } 53 } 54 } 55 int main() 56 { 57 while(scanf("%d%d",&n,&m)&&n) 58 {//枚举m个点 59 fill(vis,vis+N,0); ans = Max; 60 v.clear(); 61 for(int i=1;i<=n;i++) scanf("%d",&node[i]); 62 for(int i=1;i<=n;i++) 63 for(int j=1;j<=n;j++) 64 scanf("%d",&g[i][j]); 65 dfs(0,1,0); 66 for(int i=0;i<v.size();i++) printf("%d%c",v[i],i==v.size()-1?'\n':' '); 67 } 68 return 0; 69 }