POJ2728 Desert King 最优比率生成树

Posted Luowaterbi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ2728 Desert King 最优比率生成树相关的知识,希望对你有一定的参考价值。

一开始没理解最优比率生成树为什么要用最小生成树。
书上说的是最大生成树,我一开始觉得是最大生成树,但这样求出来是合法值的最大值,也不是题目上的最小值啊。后来我发现,是在0/1规划二分的意义上理解出错了。
在一般的二分答案中,比如函数是单调递减的,>0的都不是解,<0的都是解,=0的是我们可能要求的解里面的最大值。但是对于0/1规划,二分的是唯一解,>0、<0的都不是解,只有=0的是解。
我们设二分的比率是 k k k,树用 x x x表示,最小生成树用 x m i n x_min xmin表示,最大生成树用 x m a x x_max xmax表示, F ( k , x ) = c o s t ( x ) − k ∗ d i s ( x ) F(k,x)=cost(x)-k*dis(x) F(k,x)=cost(x)kdis(x)。固定一棵树 x x x F ( k , x ) F(k,x) F(k,x)反比于 k k k F ( k , x ) = 0 F(k,x)=0 F(k,x)=0 k k k是正解。 F ( k , x ) < 0 F(k,x)<0 F(k,x)<0时,说明这棵树的比率比 k k k小; F ( k , x ) > 0 F(k,x)>0 F(k,x)>0时,说明这棵树的比率比 k k k大。

在二分过程中,如果只保证 F ( k , x m a x ) = 0 F(k,x_max)=0 F(k,xmax)=0,那么 F ( k , x m i n ) < F ( k , x m a x ) F(k,x_min)<F(k,x_max) F(k,xmin)<F(k,xmax),即 F ( k , x m i n ) < 0 F(k,x_min)<0 F(k,xmin)<0,那么此时 x m i n x_min xmin的比率显然比 k k k小,因此 k k k需要继续二分。(此时的 k k k实际上为比例最大值。)

AC代码:

#include <cstdio>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <iomanip>
#include <cstdlib>
#include <stack>
#include <cstring>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define lep(i,a,b) for(int i=(a);i>=(b);i--) 
#define lepp(i,a,b) for(int i=(a);i>(b);i--)
#define sci(x) scanf("%d",&(x))
#define scl(x) scanf("%lld",&(x))
#define scs(x) scanf("%s",(x))
#define pri(x) printf("%d\\n",(x))
#define prl(x) printf("%lld\\n",(x))
#define prs(x) printf("%s\\n",(x))
#define pdi pair<double,int>
#define pll pair<long long,long long>
#define mp make_pair
#define All(x) x.begin(),x.end() 
#define ms(a,b) memset(a,b,sizeof(a)) 
#define INF 0x3f3f3f3f
#define INFF 0x3f3f3f3f3f3f3f3f
#define multi int T;scanf("%d",&T);while(T--) 
using namespace std;
typedef long long ll;
typedef double db;
const int N=1e3+5;
const int mod=1e9+7;
const db eps=1e-6;                                                                            
const db pi=acos(-1.0);
int n,vis[N];
db z[N][N],w[N][N],v[N][N],dis[N];
struct location
    int x,y,z;
c[N];
inline db cal(db a,db b)
    return a*a+b*b;
 
int main()
    #ifndef ONLINE_JUDGE
    freopen("D:\\\\work\\\\data.in","r",stdin);
    #endif
    while(cin>>n&&n)
        rep(i,1,n)
            cin>>c[i].x>>c[i].y>>c[i].z;
            rep(j,1,i-1)
                z[i][j]=abs(c[i].z-c[j].z);
                w[i][j]=sqrt(cal(c[i].x-c[j].x,c[i].y-c[j].y));
            
        
        db l=0,r=100;
        while(r-l>eps)
            db mid=(l+r)/2.0;
            rep(i,1,n)
                dis[i]=1e17;
                rep(j,1,i-1) v[i][j]=v[j][i]=z[i][j]-mid*w[i][j];
                vis[i]=0;
            
            dis[1]=0;
            db tmp=0,mindis=1e17;
            int pos;
            rep(i,1,n)
                mindis=1e17;
                rep(j,1,n)
                    if(vis[j]) continue;
                    if(dis[j]<mindis)
                        mindis=dis[j];
                        pos=j;
                    
                
                tmp+=dis[pos];
                vis[pos]=1;
                rep(j,1,n)
                    if(vis[j]==0&&dis[j]>v[pos][j]) 
                        dis[j]=v[pos][j];
            
            if(tmp>=0) l=mid;
            else r=mid;
        
        cout<<fixed<<setprecision(3)<<l<<endl;
    

以上是关于POJ2728 Desert King 最优比率生成树的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2728 Desert King(最优比率生成树 01分数规划)

POJ 2728 Desert King (最优比率树)

(最优比率生成树)POJ 2728 - Desert King

POJ2728Desert King 最优比率生成树

POJ2728 Desert King 最优比率生成树

poj2728 Desert King最优比率生成树Prim0/1分数规划