• LA 5717枚举+最小生成树回路性质


      1 /*LA 5717
      2 《训练指南》P343
      3 最小生成树的回路性质
      4 在生成的最小生成树上,新增一条边e(u,v)
      5 若原图上u到v的路径的最大边大于e,则删除此边,加上e,否则不变。
      6 
      7 若原图上u到v的路径的最大边的产生:BFS/DFS都可 ,nm的复杂度,从每个点出发,找到每条边,更新最大即可
      8 */
      9 
     10 #include<iostream>
     11 #include<string.h>
     12 #include<stdio.h>
     13 #include<stdlib.h>
     14 #include<cmath>
     15 #include<algorithm>
     16 #include<queue>
     17 #include<stack>
     18 #include<set>
     19 #include<map>
     20 #define LL unsigned long long
     21 #define maxn 1010
     22 #define INF 99999
     23 using namespace std;
     24 
     25 double X[maxn];
     26 double Y[maxn];
     27 int Peo[maxn];
     28 int p[maxn];
     29 double L;//最小生成树总长度
     30 double MaxDis[maxn][maxn];
     31 int n,cnt;
     32 
     33 double nextnum()
     34 {
     35     double x;
     36     scanf("%lf",&x);
     37     return x;
     38 }
     39 int nextint()
     40 {
     41     int x;
     42     scanf("%d",&x);
     43     return x;
     44 }
     45 
     46 struct Edge
     47 {
     48     double u,v,dis;
     49     bool operator<(const Edge&x)const
     50     {
     51         return dis<x.dis;
     52     }
     53     void print()
     54     {
     55         cout<<"u="<<u<<","<<"v="<<v<<","<<"dis="<<dis<<endl;
     56     }
     57 } e[maxn*maxn];
     58 
     59 vector<Edge>edges;//存储新图的边
     60 vector<int>G[maxn];//记录临街的边号
     61 
     62 double Dis(int i,int j)
     63 {
     64     double x1=X[i],x2=X[j],y1=Y[i],y2=Y[j];
     65     return (sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
     66 }
     67 
     68 int findx(int x)
     69 {
     70     if (p[x]==x) return x;
     71     else return p[x]=findx(p[x]);
     72 }
     73 
     74 void merge(int x,int y)
     75 {
     76     int px=findx(x);
     77     int py=findx(y);
     78     p[px]=py;
     79 }
     80 
     81 void init()
     82 {
     83     cin>>n;
     84     cnt=0;L=0;
     85     for(int i=1; i<=n; i++)
     86     {
     87         X[i]=nextnum();//坐标值实数
     88         Y[i]=nextnum();
     89         Peo[i]=nextint();
     90     }
     91     for(int i=1; i<=n; i++)
     92         for(int j=1; j<=n; j++)
     93         {
     94             if (i==j) continue;
     95             e[cnt++]=(Edge){i,j,Dis(i,j)};//建图
     96         }
     97 }
     98 
     99 void prim()//最小生成树&&构建新的图
    100 {
    101     for(int i=1;i<=n;i++) G[i].clear();
    102     edges.clear();
    103     for(int i=1; i<=n; i++) p[i]=i;
    104     sort(e,e+cnt);
    105 
    106     for(int i=0; i<cnt; i++)
    107     {
    108         int u=e[i].u,v=e[i].v;
    109         double dis=e[i].dis;
    110         int pu=findx(u),pv=findx(v);
    111         if (pu==pv) continue;
    112         L+=dis;
    113         merge(u,v);
    114         edges.push_back((Edge){u,v,dis});
    115         G[u].push_back(edges.size()-1);
    116         edges.push_back((Edge){v,u,dis});
    117         G[v].push_back(edges.size()-1);
    118 
    119         if (edges.size()==2*(n-1)) break;
    120     }
    121 }
    122 typedef pair<int,double> Node;//<上一个点,由起点到上一个点的通路上的最大值>
    123 void max_dis()//找到最小生成树上的任意两点之间的通路的最大的边的长度,网上大多数版本是DFS实现,故写了BFS
    124 {
    125     memset(MaxDis,0,sizeof(MaxDis));
    126     bool mark[maxn];
    127     for(int i=1;i<=n;i++)
    128     {
    129         memset(mark,0,sizeof(mark));
    130         queue<Node>Q;
    131         Q.push(make_pair(i,0));
    132         while(!Q.empty())
    133         {
    134             Node Kn=Q.front();Q.pop();
    135             int u=Kn.first;double dis=Kn.second;
    136             if (mark[u]) continue;
    137             mark[u]=true;
    138             int m=G[u].size();
    139             for(int j=0;j<m;j++)
    140             {
    141                 Edge e=edges[G[u][j]];
    142                 int v=e.v;
    143                 if (MaxDis[i][v]>0) continue;//important,小技巧,因为存的是双向边,所以必须消除回退的影响
    144                 dis=MaxDis[i][v]=max(Dis(u,v),dis);
    145                 Q.push(make_pair(v,dis));
    146             }
    147         }
    148     }
    149 }
    150 
    151 int main()
    152 {
    153     int cas=0;
    154     cin>>cas;
    155     while(cas--)
    156     {
    157         init();
    158         prim();
    159         max_dis();
    160         double ans=0;
    161         for(int i=2; i<=n; i++)//枚举每一条道路
    162             for(int j=1; j<i; j++)
    163             {
    164                 int A=Peo[i]+Peo[j];
    165                 double B=L-MaxDis[i][j];
    166                 ans=max(ans,A/B);
    167             }
    168         printf("%.2lf
    ",ans);
    169     }
    170     return 0;
    171 }
  • 相关阅读:
    2018上C语言程序设计(高级)作业-第0次作业
    最后一次作业-- 总结报告
    第14、15教学周作业
    第七周作业
    第六周作业
    第四周作业
    C语言--第四次作业
    C语言--第三次作业
    C-语言第二次作业(大一下)
    TRY
  • 原文地址:https://www.cnblogs.com/little-w/p/3595422.html
Copyright © 2020-2023  润新知