zoukankan      html  css  js  c++  java
  • UVA- 1504

    题意:

    n个点,m个边,然后给出m条边的顶点和权值,其次是q次替换,每次替换一条边,给出每次替换的边的顶点和权值,然后求出这次替换的最小生成树的值;

    最后要你输出:q次替换的平均值。其中n<3000,q<10000。

    分析:

    我们可以先求最小生成树,对于最小生成树的每一条边,我们要找到它的最佳替代边,使其价值最小。

    具体实践方法:

    树形dp,从每个点dfs一次,每次把i当成根,其余都是它的孩子,更新dp数组,对于i点为根的除j之外的所有的

    子树中的所有点到j距离最小值。每次从一个点root开始dfs,搜索到最后一个叶子,开始看G[root][u]的大小,保证(root,u)

    不是MST上的的边,那么一路返回,连接叶子节点的那条边的最佳替换边就是G[root][u]的大小,再继续返回,

    此过程要看,map[root][...]的大小,其中[...]表示从叶子节点一路返回过来的点。

    // File Name: 1504.cpp
    // Author: Zlbing
    // Created Time: 2013/6/17 19:36:53
    
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    #include<cstdio>
    #include<set>
    #include<map>
    #include<vector>
    #include<cstring>
    #include<stack>
    #include<cmath>
    #include<queue>
    using namespace std;
    #define CL(x,v); memset(x,v,sizeof(x));
    #define INF 0x3f3f3f3f
    #define LL long long
    #define REP(i,r,n) for(int i=r;i<=n;i++)
    #define RREP(i,n,r) for(int i=n;i>=r;i--)
    
    const int MAXN=3050;
    struct Edge{
        int u,v,cost;
        bool operator <(const Edge &rsh)const{
            return cost<rsh.cost;    
        }
    };
    vector<Edge>edges;
    vector<int> mst[MAXN];
    int gmst[MAXN][MAXN];
    int f[MAXN];
    int dp[MAXN][MAXN];
    int G[MAXN][MAXN];
        int n,m,Q;
        int ans=0;
    int find(int x)
    {
        return f[x]==x?x:f[x]=find(f[x]);
    }
    void kruscal()
    {
        ans=0;
        CL(gmst,0);
        for(int i=0;i<=n;i++)f[i]=i;
        for(int i=0;i<m;i++)
        {
            Edge e=edges[i];
            int fu=find(e.u);
            int fv=find(e.v);
            if(fu!=fv)
            {
                ans+=e.cost;
                f[fu]=fv;
                mst[e.u].push_back(e.v);
                mst[e.v].push_back(e.u);
                gmst[e.u][e.v]=gmst[e.v][e.u]=1;
            }
        }
    }
    int dfs(int root,int u,int fa)
    {
        int s=INF;
        for(int i=0;i<mst[u].size();i++)
        {
            int v=mst[u][i];
            if(v==fa)continue;
            int tmp=dfs(root,v,u);
            s=min(s,tmp);
            dp[u][v]=dp[v][u]=min(dp[u][v],tmp);
        }
        if(root!=fa)//保证这条边不是生成树的边
            s=min(s,G[root][u]);
        return s;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            if(n==0)break;
            edges.clear();
            int a,b,c;
            REP(i,0,n)mst[i].clear();
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                {
                    dp[i][j]=INF;
                    G[i][j]=INF;
                }
            REP(i,1,m)
            {
                scanf("%d%d%d",&a,&b,&c);
                edges.push_back((Edge){a,b,c});
                G[a][b]=G[b][a]=c;
            }
            sort(edges.begin(),edges.end());
            kruscal();
            REP(i,0,n-1)
            dfs(i,i,-1);
            int sum=0;
            scanf("%d",&Q);
            REP(i,1,Q)
            {
                scanf("%d%d%d",&a,&b,&c);
                if(!gmst[a][b])
                    sum+=ans;
                else
                    sum+=ans*1.0-G[a][b]+min(dp[a][b],c);
            }
            double s=sum/(double)Q;
            printf("%.4lf
    ",s);
        }
        return 0;
    }
  • 相关阅读:
    QQ群友在线/离线,如何测试?
    QQ好友在线/离线,怎么测试?
    用户体验测试一样很重要
    BUG,带给我的思考
    chrome DevTools
    HTTP、HTTPS
    Knockout双向绑定
    微信小程序
    git fetch 更新远程代码到本地仓库
    Git 同步远程仓库
  • 原文地址:https://www.cnblogs.com/arbitrary/p/3142191.html
Copyright © 2011-2022 走看看