zoukankan      html  css  js  c++  java
  • poj1639

    题意:给一个无向图,求最小生成树,对图中的一个点进行了度数限制,其度不能超过k。

    分析:设该限制点为0号点,先将其删除,然后求各连通分支的最小生成树。然后将0点加回图中,把0点与各个连通分支中与它最近的点相连。

    然后可能现在0点的度小于限制,我们不断的增加0点的度,直到超过限制,观察什么时候最小生成树的总长度最小。

    对于每次给0点加边我们需要进行一下操作:先以0号点为根,计算出图中各个点通过树枝边到0号点的路径中的最长边长度(BFS或DFS实现)。然后,对于0点的各个非树枝边,我们尝试着选择一个加到树中,加入树中后必然产生环,我们进行破环(删掉环上的某条边),看加哪个边并破环后得到的最小生成树最小,就加那条边并破环。破环的方法如下:例如,我们将0点与a点的边加入树中,则原来a点到0点的树枝边路径中需要有一个边被去掉,我们为了让最小生成树较小,我们选择去掉那条路径上最长的边,这在之前已经计算出来了。

    View Code
    //poj1639
    #include <iostream>
    #include <string>
    #include <queue>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const    int        maxv = 110;
    
    struct edge
    {
        int        w, v1, v2;
        edge(int ww, int vv1, int vv2):w(ww), v1(vv1), v2(vv2){}
        edge(){}
    }edges[maxv * maxv], bestedge[maxv];
    
    int        n, namecount, father[maxv], areacount, best[maxv], limit, answer, fans;
    string    names[maxv];
    bool    used[maxv][maxv];
    vector<vector<edge>>map(maxv);
    
    
    int getid(string name)
    {
        int        i;
    
        for (i = 0; i < namecount; i++)
            if (name == names[i])
                return i;
        names[namecount++] = name;
        return namecount - 1;
    }
    
    void init()
    {
        int        i, length, n1, n2;
        string    name1, name2;
    
        memset(used, 0, sizeof(used));
        scanf("%d", &n);
        namecount = 1;
        answer = 0;
        areacount = 0;
        names[0] = "Park";
        for (i = 0; i < n; i++)
        {
            getchar();
            cin >> name1;
            cin >> name2;
            cin >> length;
            n1 = getid(name1);
            n2 = getid(name2);
            map[n1].push_back(edge(length, n2, -1));
            map[n2].push_back(edge(length, n1, -1));
            edges[i].v1 = n1;
            edges[i].v2 = n2;
            edges[i].w = length;
        }
        scanf("%d", &limit);
    }
    
    bool operator< (edge a, edge b)
    {
        return a.w < b.w;
    }
    
    int getanc(int a)
    {
        if (father[a] != a)
            return father[a] = getanc(father[a]);
        return a;
    }
    
    void makeareas()
    {
        int        i, n1, n2;
    
        for (i = 0; i < namecount; i++)
            father[i] = i;
        sort(edges, edges + n);
        for (i = 0; i < n; i++)
        {
            if (edges[i].v1 == 0 || edges[i].v2 == 0)
                continue;
            n1 = getanc(edges[i].v1);
            n2 = getanc(edges[i].v2);
            if (n1 == n2)
                continue;
            father[n1] = n2;
            used[edges[i].v1][edges[i].v2] = true;
            used[edges[i].v2][edges[i].v1] = true;
        }
        for (i = 1; i < namecount; i++)
            if (father[i] == i)
                areacount++;
    }
    
    void maketree()
    {
        int        vdist[maxv], n1, i, vconect[maxv];
    
        memset(vconect, -1, sizeof(vconect));
        for (i = 0; i < map[0].size(); i++)
        {
            n1 = getanc(map[0][i].v1);
            if (vconect[n1] == -1 || vdist[n1] > map[0][i].w)
            {
                vconect[n1] = map[0][i].v1;
                vdist[n1] = map[0][i].w;
            }
        }
        for (i = 1; i < namecount; i++)
        {
            if (father[i] != i)
                continue;
            used[vconect[i]][0] = true;
            used[0][vconect[i]] = true;
        }
    }
    
    void calculate()
    {
        int        i;
    
        for (i = 0; i < n; i++)
            if (used[edges[i].v1][edges[i].v2])
                answer += edges[i].w;
        fans = answer;
    }
    
    void dp()
    {
        int        i, l, vused[maxv];
    
        queue<int> q;
        memset(father, -1, sizeof(father));
        memset(vused, 0, sizeof(vused));
        memset(best, 0, sizeof(best));
        memset(bestedge, 0, sizeof(bestedge));
        vused[0] = true;
        for (i = 0; i < map[0].size(); i++)
            if (used[0][map[0][i].v1])
            {
                q.push(map[0][i].v1);
                father[map[0][i].v1] = 0;
                vused[map[0][i].v1] = true;
            }
        while (!q.empty())
        {
            l = q.front();
            for (i = 0; i < map[l].size(); i++)
                if (!vused[map[l][i].v1] && used[l][map[l][i].v1])
                {
                    vused[map[l][i].v1] = true;
                    q.push(map[l][i].v1);
                    if (best[l] > map[l][i].w)
                    {
                        best[map[l][i].v1] = best[l];
                        bestedge[map[l][i].v1] = bestedge[l];
                    }
                    else
                    {
                        best[map[l][i].v1] = map[l][i].w;
                        bestedge[map[l][i].v1] = map[l][i];
                        bestedge[map[l][i].v1].v2 = l;
                    }
                }
            q.pop();
        }
    }
    
    void up1()
    {
        int        dis = 1000000000, besti, i;
    
        for (i = 0; i < map[0].size(); i++)
            if (!used[0][map[0][i].v1] && dis > map[0][i].w - best[map[0][i].v1])
            {
                dis = map[0][i].w - best[map[0][i].v1];
                besti = map[0][i].v1;
            }
        used[0][besti] = true;
        used[besti][0] = true;
        answer += dis;
        if (answer < fans)
            fans = answer;
        used[bestedge[besti].v1][bestedge[besti].v2] = false;
        used[bestedge[besti].v2][bestedge[besti].v1] = false;
    }
    
    int main()
    {
        int        i;
    
        //freopen("t.txt", "r", stdin);
        init();
        makeareas();
        maketree();
        calculate();
        for (i = areacount; i < limit; i++)
        {
            dp();
            up1();
        }
        printf("Total miles driven: %d\n", fans);
        return 0;
    }
  • 相关阅读:
    JS基础类型和引用类型
    ul的margin撑不开想要的距离的办法
    html中的列表
    BEM的命名规则
    意义模糊的函数签名……文档注释
    最基础,新手入门第一段代码
    Cookie的使用
    用servlet校验密码2
    用servlet进行用户名和密码校验
    登录页面
  • 原文地址:https://www.cnblogs.com/rainydays/p/2778980.html
Copyright © 2011-2022 走看看