hdu 4756是南京网赛的题,这题和2011年福州现场赛的一道题,也就是hdu4126很像,比赛前十几天明明做过的说,结果比赛的时候没看到这题,唉。今天一不小心又翻到了一个和这两题也很像的题——hdu 4081,还是2011北京现场赛的题,晕了,既然这样就直接都放在一起算了。
这三个题思路都差不多,问题都是先要求一个最小生成树,然后删掉一条边,询问剩下的最小生成树的情况(距离或者两点权值和之类的)。方法基本都是这样的:求完最小生成树以后,用dp[u][v]表示把最小生成树的边(u,v)切断以后,在两个子树中连某条边能得到的最好情况(这里以删除一条边以后剩下最小生成树的权值为例吧)。以一个点p为父节点,然后对于一条边(u,v),可以算出v及v的子树中某一点和p连边能获得的最小权值。这样将n个点都搜一遍就行了,然后根据题中的意思进行计算结果就行了。
hdu 4756 Install Air Conditioning
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; typedef long long ll; const int maxn=1000+10; const double INF=1e18; struct Edge { int u,v,next; }; struct Points { int x,y; }; Points points[maxn]; Edge edges[maxn<<1]; int head[maxn],pa[maxn],nEdge; void AddEdge(int u,int v) { nEdge++; edges[nEdge].u=u; edges[nEdge].v=v; edges[nEdge].next=head[u]; head[u]=nEdge; } double ways[maxn][maxn],dp[maxn][maxn],d[maxn]; bool vis[maxn]; void Init(int n) { for(int i=0;i<n;++i) { ways[i][i]=0; for(int j=0;j<n;++j) dp[i][j]=INF; } memset(head,0xff,sizeof(head)); nEdge=-1; } double Len(Points a,Points b) { return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y)); } double prime(int n) { for(int i=0;i<n;++i) d[i]=ways[0][i]; memset(vis,0,sizeof(vis)); memset(pa,0,sizeof(pa)); vis[0]=true;pa[0]=-1;d[0]=0; double minlen,res=0; int pos; for(int i=1;i<n;++i) { minlen=INF; for(int j=0;j<n;++j) { if(!vis[j]&&d[j]<minlen) { minlen=d[j]; pos=j; } } res+=minlen; vis[pos]=true; if(pa[pos]!=-1) { AddEdge(pos,pa[pos]); AddEdge(pa[pos],pos); } for(int k=0;k<n;++k) { if(!vis[k]&&d[k]>ways[pos][k]) { d[k]=ways[pos][k]; pa[k]=pos; } } } return res; } double dfs(int u,int fa,int p) { double res=INF; for(int k=head[u];k!=-1;k=edges[k].next) { int v=edges[k].v; if(v==fa) continue; double tmp=dfs(v,u,p); res=min(tmp,res); dp[u][v]=dp[v][u]=min(dp[u][v],tmp); } if(fa!=p) res=min(res,ways[u][p]); return res; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t,n,k; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); Init(n); for(int i=0;i<n;++i) scanf("%d%d",&points[i].x,&points[i].y); for(int i=0;i<n;++i) for(int j=i+1;j<n;++j) ways[i][j]=ways[j][i]=Len(points[i],points[j]); double tmp=prime(n); double ans=tmp; for(int i=0;i<n;++i) dfs(i,-1,i); int u,v; for(int i=0;i<=nEdge;i+=2) { u=edges[i].u;v=edges[i].v; if(u!=0&&v!=0) ans=max(ans,tmp-ways[u][v]+dp[u][v]); } printf("%.2lf\n",ans*k); } return 0; }
hdu 4126 Genghis Khan the Conqueror
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<set> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; typedef long long ll; const int maxn=3000+10; struct Edge { int v; int next; }; Edge edges[maxn<<1]; int head[maxn],nEdge; int way[maxn][maxn],dis[maxn],pa[maxn],dp[maxn][maxn]; bool vis[maxn]; int n,m; void clearAll() { memset(vis,0,sizeof(vis)); memset(head,0xff,sizeof(head)); for(int i=0;i<n;++i) for(int j=0;j<n;++j) dp[i][j]=way[i][j]=inf; nEdge=-1; } void AddEdges(int u,int v) { nEdge++; edges[nEdge].v=v; edges[nEdge].next=head[u]; head[u]=nEdge; } ll prim() { for(int i=0;i<n;++i) {dis[i]=way[0][i];pa[i]=0;} dis[0]=0;vis[0]=true;pa[0]=-1; ll res=0; int minnum,pos; for(int i=1;i<n;++i) { minnum=inf; for(int j=0;j<n;++j) { if(!vis[j]&&dis[j]<minnum) { minnum=dis[j]; pos=j; } } res+=minnum; vis[pos]=true; if(pa[pos]!=-1) { AddEdges(pos,pa[pos]); AddEdges(pa[pos],pos); } for(int k=0;k<n;++k) { if(!vis[k]&&way[pos][k]<dis[k]) { dis[k]=way[pos][k]; pa[k]=pos; } } } return res; } int dfs(int u,int fa,int p) { int ans=inf; for(int k=head[u];k!=-1;k=edges[k].next) { int v=edges[k].v; if(v==fa) continue; int tmp=dfs(v,u,p); ans=min(ans,tmp); dp[u][v]=dp[v][u]=min(dp[u][v],tmp); } if(fa!=p) ans=min(ans,way[u][p]); return ans; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int a,b,c; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; clearAll(); for(int i=0;i<m;++i) { scanf("%d%d%d",&a,&b,&c); way[a][b]=way[b][a]=c; } double sum=0; ll val=prim(); for(int i=0;i<n;++i) dfs(i,-1,i); int q; scanf("%d",&q); for(int i=0;i<q;++i) { scanf("%d%d%d",&a,&b,&c); if(pa[a]!=b&&pa[b]!=a) sum+=val; else sum+=min(dp[a][b],c)+val-way[a][b]; } printf("%.4lf\n",sum/q); } return 0; }
hdu 4081 Qin Shi Huang's National Road System
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define eps 1e-9 #define pi acos(-1.0) using namespace std; typedef long long ll; const int maxn=1000+10; const double INF=1e10; struct Edge { int u,v,next; }; struct Point { int x,y; }points[maxn]; Edge edges[maxn<<1]; int head[maxn],nEdge; void AddEdge(int u,int v) { nEdge++; edges[nEdge].u=u; edges[nEdge].v=v; edges[nEdge].next=head[u]; head[u]=nEdge; } double Len(Point a,Point b) { return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y)); } int n,val[maxn],pa[maxn],dp[maxn][maxn]; double ways[maxn][maxn],d[maxn],ans,prval; bool vis[maxn]; void prime() { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;++i) d[i]=ways[1][i],pa[i]=1; vis[1]=true;pa[1]=-1;prval=0; double minval; int pos; for(int i=1;i<n;++i) { minval=INF; for(int j=1;j<=n;++j) { if(!vis[j]&&d[j]<minval) { minval=d[j]; pos=j; } } prval+=minval; vis[pos]=true; if(pa[pos]!=-1) { AddEdge(pos,pa[pos]); AddEdge(pa[pos],pos); } for(int k=1;k<=n;++k) { if(!vis[k]&&d[k]>ways[pos][k]) { d[k]=ways[pos][k]; pa[k]=pos; } } } } int dfs(int u,int fa,int p) { int res=0; for(int k=head[u];k!=-1;k=edges[k].next) { int v=edges[k].v; if(v==fa) continue; int tmp=dfs(v,u,p); res=max(res,tmp); dp[u][v]=dp[v][u]=max(dp[u][v],tmp); } if(u!=p) res=max(res,val[u]+val[p]); return res; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d%d%d",&points[i].x,&points[i].y,&val[i]); for(int i=1;i<=n;++i) for(int j=i;j<=n;++j) ways[i][j]=ways[j][i]=Len(points[i],points[j]); memset(head,0xff,sizeof(head)); nEdge=-1; prime(); ans=0; memset(dp,0,sizeof(dp)); for(int i=1;i<=n;++i) dfs(i,-1,i); int u,v; for(int i=0;i<=nEdge;i+=2) { u=edges[i].u;v=edges[i].v; ans=max(ans,(dp[u][v])/(prval-ways[u][v])); } printf("%.2lf\n",ans); } return 0; }