HDOJ 2489 Minimal Ratio Tree (Kruskal+Dfs)
2017-05-22 23:34
162 查看
Minimal Ratio Tree
TimeLimit: 2000/1000 MS (Java/Others) Memory Limit:32768/32768 K (Java/Others)Total Submission(s): 4294 Accepted Submission(s): 1360
Problem Description
For a tree,which nodes and edges are all weighted, the ratio of it is calculated accordingto the following equation.
Given a complete graph of n nodes with all nodes and edges weighted, your taskis to find a tree, which is a sub-graph of the original graph, with m nodes andwhose ratio is the smallest among all the trees of m nodes in the graph.
Input
Input contains multiple test cases. The first line of each test case contains twointegers n (2<=n<=15) and m (2<=m<=n), which stands for the numberof nodes in the graph and the number of nodes in the minimal ratio tree. Twozeros end the input. The next line
contains n numbers which stand for theweight of each node. The following n lines contain a diagonally symmetrical n×nconnectivity matrix with each element shows the weight of the edge connectingone node with another. Of course, the diagonal will be all 0,
since there is noedge connecting a node with itself.
All the weights of both nodes and edges (except for the ones on the diagonal ofthe matrix) are integers and in the range of [1, 100].
The figure below illustrates the first test case in sample input. Node 1 andNode 3 form the minimal ratio tree.
Output
For each test case output one line contains a sequence of the m nodes whichconstructs the minimal ratio tree. Nodes should be arranged in ascending order.If there are several such sequences, pick the one which has the smallest nodenumber; if there's a tie,
look at the second smallest node number, etc. Pleasenote that the nodes are numbered from 1 .
Sample Input
3 2
30 20 10
0 6 2
6 0 3
2 3 0
2 2
1 1
0 2
2 0
0 0
Sample Output
1 3
1 2
瞎扯:最近接触最小生成树后(其实后来发现跟以前的并查集差不多。。。),发现题目千变万化,但全都是套模板(最近为了让自己打代码更熟练,摒弃了以前的恶习:模板题直接复制模板,转而全部自己重新默打,感觉虽然会多花些时间,但会对算法更加熟悉,慢慢养成好习惯),今天终于遇到了一道有些变化的题目。
题意:给出一系列点和边,每个边和点都有一个权值,给定一个值m,选择一系列边,使这些边把任意m个点连接起来,使边的权值和与点的权值和最小。
分析:假设我们已经选定m个点,那么点的权值就已经固定,那么我们需要做的便是使边的权值最小,易知就是求最小生成树。至于如何选定m个点,我们可以观察到点的个数最大不会超过15,所以可以用DFS爆搜,但如果DFS每一层都遍历n个点,还是会超时的,所以我们的优化方法是按照顺序搜,每一层只判断当前点选与不选,那么每一层就变成只需要遍历两个状态。
#include <bits/stdc++.h> using namespace std; #define mst(a,b) memset((a),(b),sizeof(a)) #define f(i,a,b) for(int i=(a);i<(b);++i) typedef long long ll; const int maxn= 20; const int mod = 475; const ll INF = 0x3f3f3f3f; const double eps = 1e-6; #define rush() int T;scanf("%d",&T);while(T--) int pre[maxn]; int d[maxn]; int vis[maxn]; int mp[maxn][maxn]; int output[maxn]; int n,m,cnt; double Min; struct node { int x,y,w; }a[maxn*maxn]; bool cmp(const node &a,const node &b) { return a.w<b.w; } void init() { for(int i=0;i<=n;i++) pre[i]=i; } int find(int x) { int t,r=x; while(x!=pre[x]) { x=pre[x]; } while(r!=x) { t=pre[r]; pre[r]=x; r=t; } return x; } void join(int a,int b) { int A,B; A=find(a); B=find(b); if(A!=B) pre[B]=A; } void solve(int sum2) { int sum1=0; int tot=0; cnt=0; init(); for(int i=1;i<=n;i++) { if(vis[i]==1) { for(int j=i+1;j<=n;j++) //优化1,:避免放入性质相同的边 { if(vis[j]==1) { a[cnt].x=i; a[cnt].y=j; a[cnt++].w=mp[i][j]; } } } } sort(a,a+cnt,cmp); for(int i=0;i<cnt;i++) { if(find(a[i].x)!=find(a[i].y)) { join(a[i].x,a[i].y); sum1+=a[i].w; tot++; } if(tot==m-1) //优化2:当已经找够覆盖m个点的m-1条边时,提前结束 break; } double ans=sum1*1.0/sum2; tot=0; if(ans<Min||Min==-1) { Min=ans; for(int i=1;i<=n;i++) { if(vis[i]==1) { output[tot++]=i; } } } } void dfs(int num,int now,int sum2) //num是已选择的点数,nows是当前决定是否选择的那个点的ID,sum2记录点的权值和 { if(now>n+1) //这里不是now>n,导致找了很久bug,自行理解原因 return; if(num==m) { solve(sum2); return; } vis[now]=1; dfs(num+1,now+1,sum2+d[now]); vis[now]=0; dfs(num,now+1,sum2); } int main() { while(~scanf("%d%d",&n,&m)&&(n||m)) { for(int i=1;i<=n;i++) { scanf("%d",&d[i]); } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&mp[i][j]); } mst(vis,0); Min=-1; dfs(0,1,0); for(int i=0;i<m-1;i++) { printf("%d ",output[i]); } printf("%d\n",output[m-1]); } return 0; }
相关文章推荐
- HDU2489 Minimal Ratio Tree 解题报告【图论】【Kruskal】【dfs】
- HDU 2489 Minimal Ratio Tree(DFS+Kruskal最小生成树)
- hdu 2489 Minimal Ratio Tree【Dfs+kruskal】
- hdu 2489 Minimal Ratio Tree (DFS枚举+MST)
- hdu 2489 Minimal Ratio Tree(dfs枚举 + 最小生成树)~~~
- HDU 2489 Minimal Ratio Tree(dfs+最小生成树-Prim)
- HDU 2489 Minimal Ratio Tree(DFS+prim)
- HDU 2489 Minimal Ratio Tree (DFS枚举+最小生成树Prim)
- HDU 2489 Minimal Ratio Tree (DFS枚举+最小生成树Prim)
- HDU 2489 Minimal Ratio Tree 最小生成树+DFS
- HDU 2489 Minimal Ratio Tree (dfs+Prim最小生成树)
- HDU 2489 Minimal Ratio Tree(prim+DFS)
- hdu 2489 Minimal Ratio Tree(prim+dfs)
- HDU 2489 Minimal Ratio Tree (dfs+Prim最小生成树)
- HDU 2489 Minimal Ratio Tree(dfs+最小生成树-Prim)
- HDU 2489 Minimal Ratio Tree(dfs+最小生成树)
- HDU 2489 Minimal Ratio Tree(prim+dfs)
- hdu-2489 Minimal Ratio Tree(DFS+最小生成树)
- hdu 2489 Minimal Ratio Tree dfs枚举组合情况+最小生成树★
- HDU 2489 Minimal Ratio Tree(dfs枚举+最小生成树)