1. 程式人生 > >Minimal Ratio Tree HDU 2489

Minimal Ratio Tree HDU 2489

題目連結:傳送門

 

題意:給你一個有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;
}