• 斯坦纳树应用


    点权关键联通

    定义(f[i][bit])为联通快里包含(i)且关键点状态为(bit)的最小花费

    初始化(~_{i=1}^k f[i][1<<i-1]=0;)

    实现:枚举(bit),枚举(i),枚举(S)
    (~~~~~~~~~~)(f[i][bit]=min_{Sin bit}{f[i][S]+f[i][bit-S]-val[i]})(容斥)

    (~~~~~~~~~~)显然这样仅是合并(填表),还得有向外扩展的部分(刷表)

    (~~~~~~~~~~)每次枚举(bit)最后遍历一遍图:(f[j][bit]=f[i][bit]+val[j])(e(i,j)in {E})
    (~~~~~~~~~~)注意此时即使(j)是关键点也不需要变化(bit)

    边权有色关键联通

    要求同色的关键点必须联通
    对于颜色状压处理,状压处理的那些颜色单独作为关键点联通处理

    对于之前的颜色状压做子集动规

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
    #include <algorithm>  
    #include <queue>  
    
    using namespace std;  
    const int Maxn = 0x3f3f3f3f;  
    const int N = 1005, M = 6005, L = 1 << 10;  
    int lst[N], f[N][L], nxt[M], to[M], cst[M], g[L], c[12];   
    int n, m, k, T, Cn; bool vis[N];  
    queue<int> Q;  
    
    template <class T> inline T Min(const T a, const T b) {return a < b? a : b;}  
    template <class T> inline void CkMin(T &a, const T b) {if (a > b) a = b;}  
    
    struct point  
    {  
        int col, id;  
        #define col(x) a[x].col  
        #define id(x) a[x].id  
    }a[12];  
    
    inline bool cmp(const point x, const point y) {return x.col < y.col;}  
    
    inline int get()  
    {  
        char ch; bool f = false; int res = 0;  
        while (((ch = getchar()) < '0' || ch > '9') && ch != '-');  
        if (ch == '-') f = true;  
         else res = ch - '0';  
        while ((ch = getchar()) >='0' && ch <= '9')  
            res = (res << 3) + (res << 1) + ch - '0';  
        return f? ~res + 1 : res;  
    }  
    
    inline void put(int x)  
    {  
        if (x < 0)  
          x = ~x + 1, putchar('-');  
        if (x > 9) put(x / 10);  
        putchar(x % 10 + 48);  
    }  
    
    inline void add(const int x, const int y, const int z)  
    {  
        nxt[++T] = lst[x]; lst[x] = T; to[T] = y; cst[T] = z;  
        nxt[++T] = lst[y]; lst[y] = T; to[T] = x; cst[T] = z;  
    }  
    
    inline void SPFA(const int I)  {  
        int x, y;  
        while (!Q.empty())  {  
            x = Q.front(); 
    		vis[x] = false; 
    		Q.pop();  
            for (int i = lst[x]; i; i = nxt[i])  
                if (f[y = to[i]][I] > f[x][I] + cst[i])  {  
                    f[y][I] = f[x][I] + cst[i];  
                    if (!vis[y]) 
    			        vis[y] = true, Q.push(y);  
                }   
        }  
    }  
    
    inline int solve(const int cnt) {  
        int Cm = 1 << cnt;  
        for (int i = 1; i < Cm; ++i)  {  
            for (int j = 1; j <= n; ++j)  {  
                for (int k = (i - 1) & i; k; k = (k - 1) & i)  
                    CkMin(f[j][i], f[j][k] + f[j][i - k]);  //边权不需要容斥 
                if (f[j][i] != Maxn) 
    			    vis[j] = true, 
    				Q.push(j);  
            }  
            SPFA(i);  
        }  
        int res = Maxn;  
        for (int i = 1; i <= n; ++i) CkMin(res, f[i][Cm - 1]);  
        return res;  
    }  
    
    int main()  
    {   
        n = get(); m = get(); k = get(); int x, y;  
        for (int i = 1; i <= m; ++i)  
        {  
            x = get(); y = get();   
            add(x, y, get());  
        }  
        for (int i = 1; i <= k; ++i)   
            col(i) = get(), 
    		id(i) = get();  //a
        sort(a + 1, a + k + 1, cmp);  //col
        for (int i = 1; i <= k; ++i)  {  
            if (col(i) != col(i - 1)) 
    		    Cn++; 
    		c[i] = Cn;  
        }  
        for (int i = 1; i <= k; ++i) col(i) = c[i]; //离散化 
        Cn = (1 << Cn);  
        memset(g, Maxn, sizeof(g));  
        for (int i = 1; i < Cn; ++i)  {  
            memset(f, Maxn, sizeof(f));  
            int cnt = 0;   
            for (int j = 1; j <= k; ++j)   
                if ((1 << col(j) - 1) & i) 
    		        f[id(j)][1 << cnt++] = 0;  
            g[i] = solve(cnt);  
         }   
        for (int i = 1; i < Cn; ++i)  
            for (int j = (i - 1) & i; j; j = (j - 1) & i)  
                CkMin(g[i], g[j] + g[i - j]);  
        return put(g[Cn - 1]), 0;  
    }  
    
  • 相关阅读:
    【动态规划】 EditDistance
    招聘
    算法01 C语言设计
    keras04
    电影《邪不压正》打动我的
    Eclipse
    6.面向对象编程(下)2
    获取一个1-100之间的随机数
    java如何使用帮助文档api
    3.java基础语法(下)
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10575179.html
Copyright © 2020-2023  润新知