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("*****\n");
 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\n",Max*val);
142     }
143 }

 

posted @ 2015-09-01 17:28  miao_a_miao  阅读(230)  评论(0编辑  收藏  举报