poj 4756 Install Air Conditioning 生成树变形

来源:互联网 发布:阿里云服务器创建快照 编辑:程序博客网 时间:2024/05/18 03:54

南京网络赛的题目

题意:有一条边不能用,但不知道是哪条,问最坏情况的最小生成树的大小。

思路:最容易想到的做法就是求最小生成树,然后枚举的删去最小生成树上的边,再求最小生成树,取最大值。n^3,              超时

           那么可以用求次小生成树的思想,求出每条最小生成树上的边的最小替代边。这个可以用树形dp的思想n^2解决。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;const int maxn=1e3+9;const double inf=1e11;double x[maxn],y[maxn];int from[maxn];int n,m;double e[maxn][maxn],g[maxn][maxn];bool visit[maxn];double key[maxn],dist[maxn];int head[maxn],lon;struct{    int to,next,from;}edge[maxn<<1];inline double min(double a,double b){    if(a<b) return a;    return b;}inline double max(double a,double b){    if(a>b) return a;    return b;}void edgeini(){    memset(head,-1,sizeof(head));    lon=0;}void edgemake(int from,int to){    edge[++lon].to=to;    edge[lon].next=head[from];    edge[lon].from=from;    head[from]=lon;}inline double cal(int t,int s){    double a=(x[t]-x[s])*(x[t]-x[s]);    double b=(y[t]-y[s])*(y[t]-y[s]);    return sqrt(a+b);}double prim(){    memset(visit,0,sizeof(visit));    visit[1]=1;    for(int i=1;i<=n;i++)    {        key[i]=e[1][i];        from[i]=1;    }    double ans=0;    for(int k=2,u;k<=n;k++)    {        double now=inf;        for(int i=1;i<=n;i++)        if(key[i]<now&&!visit[i])        {            u=i;            now=key[i];        }        ans+=key[u];        visit[u]=1;        edgemake(u,from[u]);        edgemake(from[u],u);        for(int i=1;i<=n;i++)        if(!visit[i]&&key[i]>e[u][i])        {            key[i]=e[u][i];            from[i]=u;        }    }    return ans;}double dfs(int now,int from){    double mmin=dist[now];    for(int k=head[now],u;k!=-1;k=edge[k].next)    {        u=edge[k].to;        if(u==from) continue;        mmin=min(dfs(u,now),mmin);    }    g[now][from]=g[from][now]=min(g[from][now],mmin);    return mmin;}int main(){//    freopen("in.txt","r",stdin);//    freopen("out.txt","w",stdout);    int T;    scanf("%d",&T);    while(T--)    {        edgeini();        scanf("%d %d",&n,&m);        for(int i=1;i<=n;i++)        scanf("%lf %lf",&x[i],&y[i]);        for(int i=1;i<=n;i++)        for(int j=i;j<=n;j++)        e[i][j]=e[j][i]=cal(i,j);        double ans=prim();        for(int i=1;i<=lon;i++)        g[edge[i].from][edge[i].to]=inf;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=n;j++)            dist[j]=e[i][j];            for(int k=head[i];k!=-1;k=edge[k].next)            dist[edge[k].to]=inf;            dfs(i,0);        }        double ret=ans;        for(int i=1;i<=lon;i++)        if(edge[i].from!=1&&edge[i].to!=1)        ret=max(ret,ans-e[edge[i].from][edge[i].to]+g[edge[i].from][edge[i].to]);        printf("%.2f\n",ret*m);    }    return 0;}