Minimal Ratio Tree HDU 2489
阿新 • • 發佈:2018-11-15
題目連結:傳送門
題意:給你一個有n個節點的完全雙向圖,在這張圖中找有m個結點的數,使表示式的值最小,並將節點按照字典序輸出。
做法:看到表示式第一想法是最優比例生成樹,但是找不到排序的條件,就換一種方法,題目上給的資料很小,可以嘗試著暴力一下,題目按照節點字典序輸出,我們可以深搜節點,然後將節點和節點的邊取出來,然後用 Kruskal 解決最小生成樹,最後更新答案。
程式碼:
///#include<bits/stdc++.h> ///#include<unordered_map> ///#include<unordered_set> #include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<queue> #include<set> #include<stack> #include<map> #include<new> #include<vector> using namespace std; typedef long long ll; typedef unsigned long long ull; const double pai=acos(-1.0); const double E=2.718281828459; int n,m,p[20]; double value[20],maps[20][20]; vector<int>q,ans; double minn; struct node { int s; int e; double c; }load[200]; bool cmp(node a,node b) { return a.c<b.c; } int find(int x) { return p[x]==x?x:p[x]=find(p[x]); } double Kruskal() { for(int i=1;i<=n;i++) p[i]=i; int sign=0; double ss=0; for(int i=0;i<m;i++) for(int j=i+1;j<m;j++) load[++sign]=node{q[i],q[j],maps[q[i]][q[j]]}; sort(load+1,load+1+sign,cmp); for(int i=1;i<=sign;i++) { int x=find(load[i].s),y=find(load[i].e); if(x!=y) { p[x]=y; ss+=load[i].c; } } return ss; } void dfs(int s,int k) { if(k==m) { double sum=0; for(int i=0;i<m;i++) sum+=value[q[i]]; if(Kruskal()/sum<minn) { minn=Kruskal()/sum; ans=q; } return ; } for(int i=s+1;i+m-k<=n+1;i++) { q.push_back(i); dfs(i,k+1); q.pop_back(); } return ; } int main() { while(scanf("%d %d",&n,&m)!=EOF,n+m) { minn=9999999.0; ans.clear(); for(int i=1;i<=n;i++) scanf("%lf",&value[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%lf",&maps[i][j]); for(int i=1;i<=n-m+1;i++) { q.clear(); q.push_back(i); dfs(i,1); } for(int i=0;i<m;i++) { if(i==0) printf("%d",ans[i]); else printf(" %d",ans[i]); } printf("\n"); } return 0; }