HDU

来源:互联网 发布:淘宝客怎么拉人进群 编辑:程序博客网 时间:2024/06/01 16:35

题目网址:点击打开链接

这个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了,很多东西不要简单的以为自己会了,真让你自己动手的时候才显示出真章,年轻人好好努力吧,要知道,下一个最小生成树,你可能还是不会;

原创粉丝点击