题目网址:点击打开链接
这个wa了一天的题,,,总算是知道错哪了;
这个题目的要求是找两点之间建立一条边,然后这两个点的人口数为A,B为除去这两个点之间的距离,所有点相连通的其他路的总长;
因而转化为一个次小生成树的问题,先生成一个最小生成树,然后开始删边,删一条边之后会发现,分成的两个集合中任意两个点相连,所有的点就又是相互连通的了;
这个题目由于A/B的值未知,所以每两个点都需要考虑进去,想要在任意两个点之间建路,然后B希望最小,就是从两个点之间相连的路上寻找一个最长的边删掉,然后再将这两个点连通起来,又是一个连通图;
所以这个问题的核心就在于,寻找每两个点连接路上的最大路长;
例如1——————2————3——4
|
6
如果希望在1-6之间建路的话,应该删掉的边是1-2他最长,然后连接1-6,又是一个树;
行了该上代码了
#include <iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn=1000+5;
struct node
{
int x,y;
};
struct ege
{
int e,v;
double w;
ege(int ee=0,int vv=0,double ww=0)
{
e=ee;v=vv;w=ww;
}
bool operator<(const ege& s)const
{
return w<s.w;
}
};
ege eg[maxn*maxn+5];
int p[maxn];
int pro[maxn];
int n,V,t;
node s[maxn];
double dis(int x,int y)
{
return sqrt((double)(s[x].x-s[y].x)*(s[x].x-s[y].x)*1.0+(s[x].y-s[y].y)*(s[x].y-s[y].y)*1.0);
}
void inint(int n)
{
for(int i=0;i<=n;i++)
pro[i]=i;
}
int find(int x)
{
if(x==pro[x])
return x;
else
return pro[x]=find(pro[x]);
}
void uion(int x,int y)
{
int xx=find(x);
int yy=find(y);
if(xx==yy)
return ;
else
pro[xx]=yy;
}
int same(int x,int y)
{
if(find(x)==find(y))
return 1;
else
return 0;
}
vector <ege> e2[maxn];
double kur()
{
inint(n);
double res=0;
int numm=0;
sort(eg,eg+V);
for(int i=0;i<V;i++)
{
ege ee=eg[i];
if(!same(ee.e,ee.v))
{ numm++;
uion(ee.e,ee.v);
res+=ee.w;
e2[ee.e].push_back(ee);
e2[ee.v].push_back(ege(ee.v,ee.e,ee.w));//这里之前不小心写错了
if(numm==n-1)
break;
}
}
return res;
}
int cur[maxn];
int vis[maxn];
double e[maxn][maxn];
int num;
void dfs(int c)
{
vis[c]=1;
cur[num]=c;
num++;
for(int i=0;i<e2[c].size();i++)
{
int v=e2[c][i].v;
double w=e2[c][i].w;
if(!vis[v])
{//cout<<w<<endl;
//vis[v]=1;
for(int j=0;j<num;j++)
{
e[v][cur[j]]=max(w,e[cur[j]][c]);
e[cur[j]][v]=max(w,e[cur[j]][c]); //这就是我说的那个核心部分了,
// 要注意的是,1-6 之间的最大距离应该在1-3和3-6之间产生,所以是e[6][1]=max(e[3][6]],e[1][3]);
}
dfs(v);
}
}
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s[i].x>>s[i].y>>p[i];
}
V=0;
memset(eg,0,sizeof(eg));
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
eg[V]=ege{i,j,dis(i,j)};
// cout<<dis(i,j)<<endl;;
V++;
}
for(int i=0;i<n;i++)
e2[i].clear();
double res= kur();
// cout<<res<<endl;
num = 0;
memset(vis,0,sizeof(vis));
memset(e,0,sizeof(e));
memset(cur,0,sizeof(cur));
dfs(0);
double maxx = 0;
for(int i = 0;i < n; i++)
for(int j = i + 1;j < n; j++)
{
//cout<<e[i][j]<<" ";
//cout<<" p="<<p[i]+p[j]<<endl;
double ab = (double)(p[i]+p[j])/(res-e[i][j]);
if(ab>maxx)
maxx=ab;
//cout<<maxx<<endl;
}
printf("%.2f\n",maxx);
}
// cout << "Hello world!" << endl;
return 0;
}
总算是不在wa了,很多东西不要简单的以为自己会了,真让你自己动手的时候才显示出真章,年轻人好好努力吧,要知道,下一个最小生成树,你可能还是不会;