hdu 4756 MST+树形dp ****
2015-09-01 17:28
330 查看
题意:给你n(n = 1000)个二维点,第一个点是power plant,还有n - 1个点是dormitories。然后现在知道有一条寝室到寝室的边是不能连的,但是我们不知道是哪条边,问这种情况下,最小生成树的最大值。
好题,毕竟做了一下午,注意dis要double转换
dfs求的是从cur点出发到以u为根的树的最小距离
好题,毕竟做了一下午,注意dis要double转换
dfs求的是从cur点出发到以u为根的树的最小距离
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<map> using namespace std; #define MOD 1000000007 const int INF=0x3f3f3f3f; const double eps=1e-5; typedef long long ll; #define cl(a) memset(a,0,sizeof(a)) #define ts printf("*****\n"); const int MAXN=1005; int n,m,tt; /* * Kruskal算法求MST */ const int MAXM=10000000;//最大边数 int tol;//边数,加边前赋值为0 struct Edge { int to,next; }edge[MAXM]; int head[MAXN],tot; void init() { tot = 0; memset(head,-1,sizeof(head)); } void addedge(int u,int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } bool mp[MAXN][MAXN]; double dp[MAXN][MAXN]; /* * Prim求MST * 耗费矩阵cost[][],标号从0开始,0~n-1 * 返回最小生成树的权值,返回-1表示原图不连通 */ int vis[MAXN]; double lowc[MAXN]; double Prim(double cost[][MAXN],int n)//点是0~n-1 { double ans=0; memset(vis,false,sizeof(vis)); vis[0]=-1; int last[MAXN]; last[0]=0; for(int i=1;i<n;i++)lowc[i]=cost[0][i]; for(int i=1;i<n;i++) { double minc=INF; int p=-1; for(int j=0;j<n;j++) if(vis[j]!=-1&&minc>lowc[j]) { minc=lowc[j]; p=j; } if(minc==INF)return -1;//原图不连通 mp[vis[p]][p]=mp[p][vis[p]]=1; addedge(vis[p],p); addedge(p,vis[p]); ans+=minc; vis[p]=-1; for(int j=0;j<n;j++) if(vis[j]!=-1&&lowc[j]>cost[p][j]) { vis[j]=p; lowc[j]=cost[p][j]; } } return ans; } int x[MAXN],y[MAXN]; double dist[MAXN][MAXN]; double dis(int i,int j) { return sqrt((double)(x[i]-x[j])*(double)(x[i]-x[j])+(double)(y[i]-y[j])*(double)(y[i]-y[j])); } double dfs(int cur,int u,int fa){ double res=(double)INF; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==fa)continue; double tmp=dfs(cur,v,u); dp[u][v]=dp[v][u]=min(tmp,dp[u][v]); res=min(res,tmp); } if(fa!=cur){ res=min(res,dist[cur][u]); } return res; } int main() { int i,j,k,ca=1; #ifndef ONLINE_JUDGE freopen("1.in","r",stdin); #endif scanf("%d",&tt); int val; while(tt--) { init(); tol=0; scanf("%d%d",&n,&val); cl(dist); for(i=0;i<n;i++) { scanf("%d%d",x+i,y+i); } for(i=0;i<n;i++) { for(j=0;j<n;j++) { dist[i][j]=dist[j][i]=dis(i,j); } } cl(mp); double sumw=Prim(dist,n); double Max=sumw; for(int i=0;i<n;i++) for(int j=i;j<n;j++) dp[i][j]=dp[j][i]=(double)INF; for(i=0;i<n;i++) { dfs(i,i,-1); } for(i=1;i<n;i++) //枚举每条边 { for(j=i+1;j<n;j++) { if(mp[i][j]) Max=max(Max,sumw-dist[i][j]+dp[i][j]); } } printf("%.2lf\n",Max*val); } }
相关文章推荐
- 新技术
- 手机充值
- 60个开发者不容错过的免费资源库
- 网页一键分享按钮HTML代码
- NodePad++ 添加NppaStyle.dll问题
- 清空表里的数据
- 34.iOS计算时间差,返回差值---xx天xx小时xx秒
- 35.iOS7与iOS8 适配是否开启推送功能 返回Bool值
- webService-AXis2
- SQL Helper
- android 安全之——文件加密jni实现
- 我所知道的MYSQL快速建表的3种方法
- JavaScript中this详解
- Lucene学习总结
- HDU 1402 A * B Problem Plus(FFT实现高精度乘法)
- 33.定位服务-选择使用应用程序期间或者始终闪退解决方法--定位服务
- Maven部署构件至远程仓库
- MyBatis——动态SQL
- 第8章 编程模式与设计模式
- 杭电 HDU ACM 1520 Anniversary party(树形dp 基本)