zoukankan      html  css  js  c++  java
  • SGU 206 Roads

    SGU_206

        不得不说这个题目的思想太奇葩,一时间还是不能很理解……

        首先一个贪心的思路就是,石子路的d[i]一定是小于或等于c[i]的,而非石子路的d[j]是一定大于或等于c[j]的,如果我们用x[i]描述石子路谎报的增量那么有x[i]=c[i]-d[i],用y[j]描述非石子路谎报的增量那么有y[j]=d[j]-c[j],最后目标自然就是求sum{x[i]}+sum{y[j]}的最小值了。

        接着考虑题目中给出的重要条件,即最后要让石子路形成最小生成树,那么对于任意一条非石子路,填加到最小生成树上就会形成一个环,如果这条非石子路d[j]比环上某条石子路的d[i]小的话,那么这条非石子路就可以替换掉那条石子路成为最小生成树上的边,这样就与假设的“石子路形成最小生成树”相矛盾了,因此,对于环上的任意一条石子路都有d[j]>=d[i]。

        现在条件都已经分析完了,乍看起来是个很头疼的问题,因为我们要根据推出的这些不等式来确定sum{x[i]}+sum{y[j]}的最小值,这样就可能要用到线性规划这个的东西了,至少现在我还不会线性规划……但如果将原来的不等式加以变形的话,很奇葩地就能KM挂上钩了……

        由d[j]>=d[i],我们可以得到y[j]+c[j]>=c[i]-x[i],将变量x[i]、x[j]移到一边去就得到了x[i]+y[j]>=c[i]-c[j],而这个式子和KM中的A[i]+B[j]>=G[i][j]是很像的。再联想到KM求解的过程,实际上就是在满足所有A[i]+B[j]>=G[i][j]的前提条件下,不断缩小A[i],当缩到不能缩时,也就是当出现A[i]+B[j]==G[i][j]的时候,就会完成一条匹配,于是做完KM之后实际上就保证了sum{A[i]}+sum{B[j]}的值最小了。

        这样这个题目的思路就有了,找到所有的d[j]>=d[i]的关系并转化成x[i]+y[j]>=c[i]-c[j]这样的关系,然后连一条i到j的权值为c[i]-c[j]边,如果两边点数不一样的话就补点使两边的点数相等,然后将边补全,补的边的权值都看作0,最后做完KM之后根据A[i]、B[j]的值就可以计算出d[i]、d[j]的值了。在建图的时候,如果c[i]-c[j]<0,可以直接将这条边看成0,因为增量都是正的,所以有一个隐含条件x[i]+y[j]>=0。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXN 70
    #define MAXD 410
    #define MAXM 810
    #define INF 0x3f3f3f3f
    int N, M, D, first[MAXN], e, next[MAXM], v[MAXM], w[MAXM], c[MAXM];
    int g[MAXD][MAXD], visx[MAXD], visy[MAXD], A[MAXD], B[MAXD], slack, yM[MAXD];
    void add(int x, int y, int z)
    {
        v[e] = y, w[e] = z;
        next[e] = first[x], first[x] = e ++;    
    }
    int dfs(int cur, int fa, int t, int id, int value)
    {
        int i;
        if(cur == t) return 1;
        for(i = first[cur]; i != -1; i = next[i])
            if(v[i] != fa && dfs(v[i], cur, t, id, value))
            {
                g[i / 2][id] = std::max(g[i / 2][id], w[i] - value);
                return 1;
            }
        return 0;
    }
    void init()
    {
        int i, x, y, z;
        N -= 1;
        memset(first, -1, sizeof(first)), e = 0;
        for(i = 0; i < N; i ++)
        {
            scanf("%d%d%d", &x, &y, &z);
            add(x, y, z), add(y, x, z);
        }
        memset(g, 0, sizeof(g));
        M -= N;
        for(i = 0; i < M; i ++)
        {
            scanf("%d%d%d", &x, &y, &z), c[i] = z;
            dfs(x, -1, y, i, z);    
        }
    }
    int searchpath(int cur, int n)
    {
        int i;
        visx[cur] = 1;
        for(i = 0; i < n; i ++)
            if(!visy[i])
            {
                int t = A[cur] + B[i] - g[cur][i];
                if(t == 0)
                {
                    visy[i] = 1;
                    if(yM[i] == -1 || searchpath(yM[i], n))
                    {
                        yM[i] = cur;
                        return 1;
                    }
                }
                else
                    slack = std::min(slack, t);
            }
        return 0;
    }
    void solve()
    {
        int i, j, n = std::max(N, M);
        memset(B, 0, sizeof(B[0]) * n);
        for(i = 0; i < n; i ++)
            for(j = A[i] = 0; j < n; j ++) A[i] = std::max(A[i], g[i][j]);
        memset(yM, -1, sizeof(yM[0]) * n);
        for(i = 0; i < n; i ++)
            for(;;)
            {
                slack = INF;
                memset(visx, 0, sizeof(visx[0]) * n);
                memset(visy, 0, sizeof(visy[0]) * n);
                if(searchpath(i, n)) break;
                for(j = 0; j < n; j ++) if(visx[j]) A[j] -= slack;
                for(j = 0; j < n; j ++) if(visy[j]) B[j] += slack;
            }
        for(i = 0; i < N; i ++)
            printf("%d\n",  - A[i] + w[i << 1]);
        for(i = 0; i < M; i ++)
            printf("%d\n", B[i] + c[i]);
    }
    int main()
    {
        while(scanf("%d%d", &N, &M) == 2)
        {
            init();
            solve();    
        }
        return 0;    
    }
  • 相关阅读:
    Running ASP.NET Applications in Debian and Ubuntu using XSP and Mono
    .net extjs 封装
    ext direct spring
    install ubuntu tweak on ubuntu lts 10.04,this software is created by zhouding
    redis cookbook
    aptana eclipse plugin install on sts
    ubuntu open folderpath on terminal
    ubuntu install pae for the 32bit system 4g limited issue
    EXT Designer 正式版延长使用脚本
    用 Vagrant 快速建立開發環境
  • 原文地址:https://www.cnblogs.com/staginner/p/2646472.html
Copyright © 2011-2022 走看看