• hdu 4756 MST+树形dp ****


    题意:给你n(n = 1000)个二维点,第一个点是power plant,还有n - 1个点是dormitories。然后现在知道有一条寝室到寝室的边是不能连的,但是我们不知道是哪条边,问这种情况下,最小生成树的最大值。

    好题,毕竟做了一下午,注意dis要double转换

    dfs求的是从cur点出发到以u为根的树的最小距离,可以是树根,也可以是树的子节点

    枚举的边一定是在最小生成树上的,这个边被删除后,我们需要重新建立一条边来替代它,因此需要dfs来求

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<queue>
      7 #include<map>
      8 using namespace std;
      9 #define MOD 1000000007
     10 const int INF=0x3f3f3f3f;
     11 const double eps=1e-5;
     12 typedef long long ll;
     13 #define cl(a) memset(a,0,sizeof(a))
     14 #define ts printf("*****
    ");
     15 const int MAXN=1005;
     16 int n,m,tt;
     17 /*
     18 * Kruskal算法求MST
     19 */
     20 const int MAXM=10000000;//最大边数
     21 int tol;//边数,加边前赋值为0
     22 struct Edge
     23 {
     24     int to,next;
     25 }edge[MAXM];
     26 int head[MAXN],tot;
     27 void init()
     28 {
     29     tot = 0;
     30     memset(head,-1,sizeof(head));
     31 }
     32 void addedge(int u,int v)
     33 {
     34     edge[tot].to = v; edge[tot].next = head[u];
     35     head[u] = tot++;
     36 }
     37 bool mp[MAXN][MAXN];
     38 double dp[MAXN][MAXN];
     39 /*
     40 * Prim求MST
     41 * 耗费矩阵cost[][],标号从0开始,0~n-1
     42 * 返回最小生成树的权值,返回-1表示原图不连通
     43 */
     44 int vis[MAXN];
     45 double lowc[MAXN];
     46 double Prim(double cost[][MAXN],int n)//点是0~n-1
     47 {
     48     double ans=0;
     49     memset(vis,false,sizeof(vis));
     50     vis[0]=-1;
     51     int last[MAXN];
     52     last[0]=0;
     53     for(int i=1;i<n;i++)lowc[i]=cost[0][i];
     54     for(int i=1;i<n;i++)
     55     {
     56         double minc=INF;
     57         int p=-1;
     58         for(int j=0;j<n;j++)
     59             if(vis[j]!=-1&&minc>lowc[j])
     60             {
     61                 minc=lowc[j];
     62                 p=j;
     63             }
     64         if(minc==INF)return -1;//原图不连通
     65         mp[vis[p]][p]=mp[p][vis[p]]=1;
     66         addedge(vis[p],p);
     67         addedge(p,vis[p]);
     68         ans+=minc;
     69         vis[p]=-1;
     70         for(int j=0;j<n;j++)
     71             if(vis[j]!=-1&&lowc[j]>cost[p][j])
     72             {
     73                 vis[j]=p;
     74                 lowc[j]=cost[p][j];
     75             }
     76     }
     77     return ans;
     78 }
     79 int x[MAXN],y[MAXN];
     80 double dist[MAXN][MAXN];
     81 double dis(int i,int j)
     82 {
     83     return sqrt((double)(x[i]-x[j])*(double)(x[i]-x[j])+(double)(y[i]-y[j])*(double)(y[i]-y[j]));
     84 }
     85 double dfs(int cur,int u,int fa){
     86         double res=(double)INF;
     87         for(int i=head[u];i!=-1;i=edge[i].next){
     88             int v=edge[i].to;
     89             if(v==fa)continue;
     90             double tmp=dfs(cur,v,u);
     91             dp[u][v]=dp[v][u]=min(tmp,dp[u][v]);
     92             res=min(res,tmp);
     93         }
     94         if(fa!=cur){
     95             res=min(res,dist[cur][u]);
     96         }
     97         return res;
     98     }
     99 int main()
    100 {
    101     int i,j,k,ca=1;
    102     #ifndef ONLINE_JUDGE
    103     freopen("1.in","r",stdin);
    104     #endif
    105     scanf("%d",&tt);
    106     int val;
    107     while(tt--)
    108     {
    109         init();
    110         tol=0;
    111         scanf("%d%d",&n,&val);
    112         cl(dist);
    113         for(i=0;i<n;i++)
    114         {
    115             scanf("%d%d",x+i,y+i);
    116         }
    117         for(i=0;i<n;i++)
    118         {
    119             for(j=0;j<n;j++)
    120             {
    121                 dist[i][j]=dist[j][i]=dis(i,j);
    122             }
    123         }
    124         cl(mp);
    125         double sumw=Prim(dist,n);
    126         double Max=sumw;
    127         for(int i=0;i<n;i++)
    128                 for(int j=i;j<n;j++)
    129                     dp[i][j]=dp[j][i]=(double)INF;
    130         for(i=0;i<n;i++)
    131         {
    132             dfs(i,i,-1);
    133         }
    134         for(i=1;i<n;i++)  //枚举每条边
    135         {
    136             for(j=i+1;j<n;j++)
    137             {
    138                 if(mp[i][j])    Max=max(Max,sumw-dist[i][j]+dp[i][j]);
    139             }
    140         }
    141         printf("%.2lf
    ",Max*val);
    142     }
    143 }
  • 相关阅读:
    坚决不再犯的脑残错误
    2018.8.21提高A&省选组模拟考试
    2018.10.9模拟考试
    fread()快读
    2018.10.6模拟考试
    2018.10.4模拟考试
    2018.8.20提高AB组模拟考试
    2018.8.21提高AB组模拟考试
    2018.8.19提高B组模拟考试
    2018.8.18提高B组模拟试题
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4776309.html
Copyright © 2020-2023  润新知