LA 5713

LA 5713

要求A/B最大,那我們先保證B最小,然後枚舉A。先求出最小生成樹,並在樹上深搜,記錄下maxcost[u][v],即樹上點u到點v之間的最長的邊。
再枚舉A,即枚舉法術邊的兩個端點i和j,刪去樹中i到j路徑上的最長邊,加入用法術邊(i,j)。此時最小生成樹權值變成了sum-maxcost[i][j]。
求出min((W[i]+W[j])/(sum-maxcost[i][j]))即可。

#include<map>
#include<cmath>
#include<ctime>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<string>
#define LL long long
#define mm0(a) memset(a,0,sizeof(a))
#define mm(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxe=1e6+5;
const int maxn=1e3+5;
const double Inf=1e18;
struct Edge{
    int to, next;
    double dist;
    Edge(){}
    Edge(int a,int b,double c):to(a), next(b), dist(c){}
};
int n, ecnt;
Edge edges[maxe];
double x[maxn], y[maxn];
int W[maxn], head[maxn], intree[2*maxe], costfrom[maxn], vis[maxn];
double maxcost[maxn][maxn];
double lowcost[maxn];
vector<int> nodes;
void Init(int n){
    ecnt=0;
    mm(head,-1);
    mm0(intree);
    mm0(vis);
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    maxcost[i][j]=0;
}
double dis(int a,int b){
    return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
}
void Add_Edge(int u,int v,double d){
    edges[ecnt]=Edge(v,head[u],d);
    head[u]=ecnt++;
}
double Prim(){
    double sum=0;
    for(int i=0;i<n;i++){
        lowcost[i]=Inf;
        vis[i]=0;
    }
    for(int i=head[0];i!=-1;i=edges[i].next){
        Edge &e=edges[i];
        lowcost[e.to]=e.dist;
        costfrom[e.to]=i;
    }
    vis[0]=1;
    while(1){
        int u=n;
        lowcost[u]=Inf;
        for(int i=0;i<n;i++)
        if(!vis[i]&&lowcost[i]<lowcost[u])
            u=i;
        if(u==n) break;
        vis[u]=1;
        sum+=lowcost[u];
        intree[costfrom[u]]=1;
        intree[costfrom[u]^1]=1;
        for(int i=head[u];i!=-1;i=edges[i].next){
            Edge &e=edges[i];
            if(lowcost[e.to]>e.dist){
                lowcost[e.to]=e.dist;
                costfrom[e.to]=i;
            }
        }
    }
    return sum;
}
void Dfs(int u,int fa,double cost){
    for(int i=0;i<nodes.size();i++){
        int x=nodes[i];
        maxcost[u][x]=maxcost[x][u]=max(maxcost[x][fa],cost);
    }
    nodes.push_back(u);
    for(int i=head[u];i!=-1;i=edges[i].next)
    if(intree[i]){
        Edge &e=edges[i];
        if(e.to==fa) continue;
        Dfs(e.to, u, e.dist);
    }
}
void solve(){
    double sum=Prim();
    nodes.clear();
    Dfs(0,-1,0);
    double ans=0;
    for(int i=0;i<n;i++)
    for(int j=i+1;j<n;j++)
    ans=max(ans,(W[i]+W[j])*1.0/(sum-maxcost[i][j]));
    printf("%.2lf\n",ans);
}
int main(){

//      freopen("matrix.in","r",stdin);//從in.txt中讀取數據
//      freopen("matrix.out","w",stdout);//輸出到out.txt文件
    int T;

    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        Init(n);
        for(int i=0;i<n;i++){
            scanf("%lf%lf%d",&x[i],&y[i],&W[i]);
        }
        for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++){
            Add_Edge(i,j,dis(i,j));
            Add_Edge(j,i,dis(i,j));
        }
        solve();
    }

    return 0;
}
發佈了54 篇原創文章 · 獲贊 3 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章