hdu2489 Minimal Ratio Tree dfs+最小生成树

来源:互联网 发布:银行存取款数据库设计 编辑:程序博客网 时间:2024/06/05 15:40

题目大意是Ratio的计算方法是边的权值除以节点的权值。由此计算带有点权值和边权值的图n,计算出一个子图m,子图m的Ratio在所有m个顶点的树中是最小的。

那么对于同一m个节点的子图中,其节点的权值是相同的,只需我们找出m个节点的最小的边权值和,即最小生成树Prim。

首先将n个节点进行dfs搜索,达到m个节点的时候进行最小生成树的计算。在计算Ratio的时候要进行精度的判断,不然就是wrong answer。

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<queue>#include<cmath>#include<cctype>using namespace std;#define INF 0xffffint a[16][16];//边权值int node[16];//点权值int vit[16],vit2[16];int arr[16];//结果int dist[20];int n,m,flag;double ans;int Prim(){    int ret=0;    memset(dist,0,sizeof(dist));    int sta;    //找到搜索结果的第一个点并作为树的第一个顶点。    for(int i=1;i<=n;i++)    {        if(vit[i])        {            sta=i;            break;        }    }    vit2[sta]=1;    dist[sta]=0;    for(int i=1;i<=n;i++)    {        if(vit[i])            dist[i]=a[sta][i];    }    for(int i=1;i<m;i++)    {        int MIN=INF;        int tmp=-1;        for(int j=1;j<=n;j++)        {            if(vit[j]&&!vit2[j]&&MIN>dist[j])            {                MIN=dist[j];                tmp=j;            }        }        vit2[tmp]=1;        ret+=MIN;        for(int j=1;j<=n;j++)        {            if(!vit2[j]&&vit[j]&&dist[j]>a[tmp][j])            {                dist[j]=a[tmp][j];            }        }    }    return ret;}void dfs(int dep){    if(flag == m)    {        memset(vit2,0,sizeof(vit2));        int ret = Prim();        int sum=0;        for(int i=1;i<=n;i++)            if(vit[i])                sum+=node[i];        double ans_tmp=(double)ret/(double)sum;        if(ans_tmp-ans<-(1e-9))//这里判断精度很重要!        {            ans=ans_tmp;            for(int i=1;i<=n;i++)                arr[i]=vit[i];        }        return ;    }    for(int i=dep;i<=n;i++)    {        if(!vit[i])        {            flag++;            vit[i]=1;            dfs(i);            flag--;            vit[i]=0;        }    }    return ;}int main(){    while(cin>>n>>m)    {        if(n == 0&&m == 0)            break;        memset(a,INF,sizeof(a));        for(int i=1;i<=n;i++)            cin>>node[i];        for(int i=1;i<=n;i++)            for(int j=1;j<=n;j++)                cin>>a[i][j];        ans=(double)INF;        memset(vit,0,sizeof(vit));        flag=0;        dfs(1);        bool ans_flag=true;        for(int i=1;i<=n;i++)        {            if(arr[i])            {                if(ans_flag)                {                    cout<<i;                    ans_flag = false;                }                else                    cout<<" "<<i;            }        }        cout<<endl;    }}


原创粉丝点击