hdu4756(最小生成树最佳替换边)

来源:互联网 发布:离线翻译软件 知乎 编辑:程序博客网 时间:2024/05/01 19:08

链接:点击打开链接

题意:给出n个点要求依次删除最小生成树上的边后,求出每次删边后的最小生成树的最大值

代码:

#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int INF=0x3f3f3f3f;int son[1005],dfs_sort[1005],dfs_num[1005];int n,id,vis[1005],fa[1005];double sum,dis[1005],dp[1005][1005],G[1005][1005];double prim(int v){    int i,j,u;    double tmp;    sum=0;    for(i=1;i<=n;i++){        dis[i]=G[v][i];        vis[i]=0;    }    dis[v]=0,vis[v]=1;    for(i=2;i<=n;i++){        tmp=(double)INF;        u=v;        for(j=1;j<=n;j++)        if(dis[j]<tmp&&vis[j]==0){            tmp=dis[j];            u=j;        }        sum+=tmp;        vis[u]=1;        for(j=1;j<=n;j++)        if(G[u][j]<dis[j]&&vis[j]==0){        fa[j]=u;        dis[j]=G[u][j];        }    }    return sum;}void dfs(int s){    int i;    vis[s]=1;    dfs_num[s]=id;    dfs_sort[id++]=s;    for(i=1;i<=n;i++){        if(fa[i]==s&&vis[i]==0){            dfs(i);            son[s]+=son[i];        }    }}int main(){                                     //跟hdu4126几乎是一样的,主要思想都是求    double cnt,ans[1005];                       //删除一条边后的最佳替换边    int x[1005],y[1005];                        //可以先看hdu4126    int t,m,i,j,u,v,num1,num2;                  //http://blog.csdn.net/stay_accept/article/details/51764084    scanf("%d",&t);    while(t--){        scanf("%d%d",&n,&m);        for(i=1;i<=n;i++)        fa[i]=son[i]=1;        fa[1]=-1;        for(i=1;i<=n;i++)        scanf("%d%d",&x[i],&y[i]);        for(i=1;i<=n;i++)        for(j=i;j<=n;j++)                       //一定要转换成double        G[i][j]=G[j][i]=sqrt((double)(x[i]-x[j])*(double)(x[i]-x[j])+(double)(y[i]-y[j])*(double)(y[i]-y[j]));        for(i=1;i<=n;i++)        vis[i]=0;        sum=prim(1);        for(i=1;i<=n;i++)        vis[i]=0;        id=1;        dfs(1);        for(i=1;i<=n;i++){            for(j=1;j<=n;j++){                dp[i][j]=(double)INF;                num1=dfs_sort[i],num2=dfs_sort[j];                if(fa[num1]!=num2&&fa[num2]!=num1)                dp[i][j]=G[num1][num2];            }        }        for(i=1;i<=n;i++)        for(j=n;j>=1;j--)        dp[i][dfs_num[fa[dfs_sort[j]]]]=min(dp[i][dfs_num[fa[dfs_sort[j]]]],dp[i][j]);        cnt=sum;        for(i=1;i<=n;i++)        ans[i]=-1.0;        for(j=2;j<=n;j++){            u=fa[j],v=j;            if(u==1)                            //第一个点直接忽略            continue;            if(ans[v]!=-1)            cnt=max(cnt,sum-G[u][v]+ans[v]);            else{                ans[v]=(double)INF;                for(i=1;i<=n;i++){                    if(dfs_num[i]<dfs_num[v]||dfs_num[i]>dfs_num[v]+son[v]-1)                    ans[v]=min(ans[v],dp[dfs_num[i]][dfs_num[v]]);                    else                    ans[v]=min(ans[v],dp[dfs_num[u]][dfs_num[v]]);                }                cnt=max(cnt,sum-G[u][v]+ans[v]);            }        }        printf("%.2lf\n",cnt*m);    }    return 0;}

1 0