• HDU 4085 Peach Blossom Spring


    HDU_4085

        去年去北京时用网络流死磕这题导致了全场悲剧,今年再做依旧毫无头绪,找到题解一看瞬间震惊了,斯坦纳树(Stenier tree)是什么东东(不过后来发现其实解法就是个状态压缩dp,只不过要借助spfa完成状态转移)……于是只好一点点学习别人的代码了,现在自己理解的还不是很透彻,推荐一篇感觉写得还不错的文章:http://endlesscount.blog.163.com/blog/static/821197872012525113427573/,回头再多做些有关的题目加深一下理解。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 60
    #define MAXM 2010
    #define MAXQ 2000010
    #define ST 1034
    #define INF 0x3f3f3f3f
    const int Q = 2000000;
    int N, M, K, bit[MAXD], first[MAXD], e, next[MAXM], v[MAXM], w[MAXM];
    int q[MAXQ], inq[MAXD][ST], front, rear, f[MAXD][ST], dp[ST];
    void add(int x, int y, int z)
    {
        v[e] = y, w[e] = z;
        next[e] = first[x], first[x] = e ++;    
    }
    void init()
    {
        int i, x, y, z;
        scanf("%d%d%d", &N, &M, &K);
        memset(first, -1, sizeof(first));
        e = 0;
        for(i = 0; i < M; i ++)
        {
            scanf("%d%d%d", &x, &y, &z);
            add(x, y, z), add(y, x, z);    
        }
    }
    int Min(int x, int y)
    {
        return x < y ? x : y;    
    }
    void spfa()
    {
        int i, x, st, y, nst;
        while(front != rear)
        {
            x = q[front] & 1023, st = q[front] >> 10;
            inq[x][st] = 0;
            ++ front > Q ? front = 0 : 0;
            for(i = first[x]; i != -1; i = next[i])
            {
                y = v[i], nst = st | bit[y];
                if(f[x][st] + w[i] < f[y][nst])
                {
                    f[y][nst] = f[x][st] + w[i];
                    if(nst == st && !inq[y][nst])
                    {
                        q[rear ++] = nst << 10 | y, inq[y][nst] = 1;
                        rear > Q ? 0 : 0;    
                    }
                }
            }
        }
    }
    int check(int st)
    {
        int i, a = 0;
        for(i = 0; i < K; i ++)
        {
            if(st & 1 << i) ++ a;
            if(st & 1 << K + i) -- a;    
        }
        return a == 0;
    }
    void solve()
    {
        int i, j, k, nn = 1 << 2 * K;
        memset(f, 0x3f, sizeof(f));
        memset(bit, 0, sizeof(bit));
        for(i = 1; i <= K; i ++)
        {
            bit[i] = 1 << (i - 1), f[i][bit[i]] = 0;
            bit[N - K + i] = 1 << (K + i - 1), f[N - K + i][bit[N - K + i]] = 0;
        }
        front = rear = 0;
        memset(inq, 0, sizeof(inq));
        for(i = 0; i < nn; i ++)
        {
            for(j = 1; j <= N; j ++)
            {
                for(k = i - 1 & i; k; k = k - 1 & i) // 枚举i的所有子集 
                    f[j][i] = Min(f[j][i], f[j][k | bit[j]] + f[j][i - k | bit[j]]);
                if(f[j][i] < INF)
                {
                    q[rear ++] = i << 10 | j, inq[j][i] = 1;
                    rear > Q ? rear = 0 : 0;
                }
            }
            spfa();
        }
        memset(dp, 0x3f, sizeof(dp));
        for(i = 0; i < nn; i ++)
            for(j = 1; j <= N; j ++)
                dp[i] = Min(dp[i], f[j][i]);
        for(i = 0; i < nn; i ++)
            if(check(i))
            {
                for(j = i - 1 & i; j; j = j - 1 & i)
                    if(check(j))
                        dp[i] = Min(dp[i], dp[j] + dp[i - j]);    
            }
        if(dp[nn - 1] == INF)
            printf("No solution\n");
        else
            printf("%d\n", dp[nn - 1]);
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            init();
            solve();
        }
        return 0;    
    }
  • 相关阅读:
    JS创建对象的四种简单方式 (工厂模式和自定义构造函数创建对象的区别)
    对js原型对象、实例化对象及prototype属性的一些见解
    Javascript中的undefined、null、""、0值和false的区别总结
    new Function()语法
    声明函数的方法 之 语句定义法(函数声明法)和表达式定义法(函数表达式)
    匿名函数function前面的! ~等符号作用小解
    proxyTable设置代理解决跨域问题
    vue之递归组件实现树形目录
    关于页面出现弹窗时,页面还可以滚动问题
    倒计时功能
  • 原文地址:https://www.cnblogs.com/staginner/p/2619857.html
Copyright © 2020-2023  润新知