zoukankan      html  css  js  c++  java
  • bzoj4774 修路

    4774: 修路

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 290  Solved: 137
    [Submit][Status][Discuss]

    Description

    村子间的小路年久失修,为了保障村子之间的往来,法珞决定带领大家修路。对于边带权的无向图 G = (V, E),
    请选择一些边,使得1 <= i <= d, i号节点和 n - i + 1 号节点可以通过选中的边连通,最小化选中的所有边
    的权值和。
     

    Input

    第一行两个整数 n, m,表示图的点数和边数。接下来的 m行,每行三个整数 ui, vi, wi,表示有一条 ui 与 vi 
    之间,权值为 wi 的无向边。
    1 <= d <= 4
    2d <= n <= 10^4
    0 <= m <= 10^4
    1 <= ui, vi <= n
    1 <= wi <= 1000

    Output

    一行一个整数,表示答案,如果无解输出-1

    Sample Input

    10 20 1
    6 5 1
    6 9 4
    9 4 2
    9 4 10
    6 1 2
    2 3 6
    7 6 10
    5 7 1
    9 7 2
    5 9 10
    1 6 8
    4 7 4
    5 7 1
    2 6 9
    10 10 6
    8 7 2
    10 9 10
    1 2 4
    10 1 8
    9 9 7

    Sample Output

    8
    分析:斯坦纳树模板题.维护数组f[i][j]表示从i出发,使得状态为j的最小花费,这里的状态是用二进制表示的:01010101之类的,如果第i位为1,表示第i号点已经被连通.再维护一个数组g[i],表示状态为j的最小花费,这里就不管是从哪个点出发了.g[j] = min{f[i][j]}.
             最后更新g[i]用i的子集更新.若i的子集j满足条件(如果点p连通了,那么点p+d也连通),并且j^i也满足条件,就更新g[i].为什么要判断是否满足条件才能更新呢?例子:
    ,上下之间的点都是要配对的,如果直接合并了,则可能不配对.
    最后输出答案g[1 << (2 * d) - 1].
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 20010,inf = 0x7ffffff;
    
    int n,m,d,head[maxn],to[maxn],nextt[maxn],w[maxn],tot = 1,f[maxn][1 << 9],g[1 << 9],maxx,vis[maxn],dis[maxn];
    queue <int> q;
    
    void add(int x,int y,int z)
    {
        w[tot] = z;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    }
    
    void spfa(int sta)
    {
        memset(vis,0,sizeof(vis));
        queue <int> q;
        for (int i = 1; i <= n; i++)
        {
            q.push(i);
            vis[i] = 1;
        }
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (f[v][sta] > f[u][sta] + w[i])
                {
                    f[v][sta] = f[u][sta] + w[i];
                    if (!vis[v])
                    {
                        vis[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
    }
    
    bool check(int sta)
    {
        for (int i = 0; i < d; i++)
        {
            int temp = 1 << i;
            if (sta & temp)
            {
                int temp2 = 1 << (i + d);
                if (!(sta & temp2))
                    return false;
            }
            temp = 1 << (i + d);
            if (sta & temp)
            {
                int temp2 = 1 << i;
                if (!(sta & temp2))
                    return false;
            }
        }
        return true;
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&d);
        for (int i = 1; i <= m; i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
        }
        maxx = (1 << (2 * d));
        for (int i = 1; i <= n; i++)
            for (int j = 0; j < maxx; j++)
                f[i][j] = inf,g[j] = inf;
        for (int i = 1; i <= d; i++)
        {
            f[i][1 << (i - 1)] = 0;
            f[n - i + 1][1 << (d + i - 1)] = 0;
        }
    
        for (int j = 0; j < maxx; j++)
        {
            for (int i = 1; i <= n; i++)
            {
                for (int k = j; k; k = (k - 1) & j)
                    f[i][j] = min(f[i][j],f[i][k] + f[i][j ^ k]);
            }
            spfa(j);
            for (int i = 1; i <= n; i++)
                g[j] = min(g[j],f[i][j]);
        }
        for (int i = 0; i < maxx; i++)
            for (int j = i; j; j = (j - 1) & i)
                if (check(j) && check(i ^ j))
                    g[i] = min(g[i],g[j] + g[j ^ i]);
        if (g[maxx - 1] < inf)
            printf("%d
    ",g[maxx - 1]);
        else
            puts("-1");
    
        return 0;
    }
  • 相关阅读:
    C语言第五次作业
    c语言第4次作业
    第12次作业
    C语言第9次作业
    C语言第8次作业2
    C语言第8次作业
    C语言第七次作业---要死了----
    C语言第七次作业
    物联网工程实践第二次作业
    物联网工程实践第一次作业
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8305767.html
Copyright © 2011-2022 走看看