[BZOJ3380] [Usaco2004 Open]Cave Cows 1 洞穴里的牛之一

Description

    很少人知道其实奶牛非常喜欢到洞穴里面去探险。
    洞窟里有N(1≤N≤100)个洞室,由M(1≤M≤1000)条双向通道连接着它们.每对洞室间
至多只有一条双向通道.有K(1≤K≤14)个洞室,里面放有1捆干草.牛吃1捆干草,体重指数就会增加1.
    贪吃的贝茜要到洞窟里面探险.她希望能吃尽量多的干草,但每条通道有一个宽度阈值,如果体重指数超过相应的阈值,贝茜就会被卡祝她从洞窟1出发,体重指数为0.在洞里溜达一圈后,她要返回洞窟1.    那她最多能吃多少捆干草呢?注意,贝茜经过一个洞室,不一定非要吃掉里面的干草.

Input

    第1行输入N,M,K,之后K行每行一个整数,表示在这个洞室放有一捆干草;接下来M行每行三个整数,表示一条双向通道的起点终点和宽度阈值.

Output

 
    最多能吃掉的干草数.

Sample Input

6 7 5
1
2
3
4
5
1 2 3
3 6 2
6 2 10
2 4 1
5 1 1
4 5 1
1 6 1

Sample Output

4
 

 
设$f[i][j]$为目前在第$i$个关键点,吃过甘草的关键点的状态是$j$是否可行。
然后用Floyd处理出任意两点之间的路径上可以通过的最大的肥胖度。
然后随便转移一下。
Floyd的预处理部分貌似还不太熟悉...到底$i$相等的时候赋什么值好啊...
 
 

 
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define reg register
inline int read() {
    int res = 0;char ch=getchar();bool fu=0;
    while(!isdigit(ch))fu|=(ch=='-'), ch=getchar();
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return fu?-res:res;
}
#define N 105
int n, m, K;
int G[N][N];
int f[105][1<<15], bin[17], cb[1<<16];
int pos[17];

int main()
{
    n = read(), m = read(), K = read();
    for (reg int i = 1 ; i <= K ; i ++) pos[i] = read();
    memset(G, 0xcf, sizeof G);
    for (reg int i = 1 ; i <= m ; i ++)
    {
        int x = read(), y = read(), z = read();
        G[x][y] = G[y][x] = z;
    }
    for (reg int i = 1 ; i <= n ; i ++) G[i][i] = 0x3f3f3f3f;
    for (reg int k = 1 ; k <= n ; k ++)
        for (reg int i = 1 ; i <= n ; i ++)
            for (reg int j = 1 ; j <= n ; j ++)
                if (i != j and i != k and k != j) 
                    G[i][j] = max(G[i][j], min(G[i][k], G[k][j]));
    bin[0] = 1;
    for (reg int i = 1 ; i <= 16 ; i ++) bin[i] = bin[i - 1] << 1;
    for (reg int i = 1 ; i < (1 << 16) ; i ++) cb[i] = cb[i >> 1] + (i & 1);
    for (reg int i = 1 ; i <= K ; i ++) f[i][bin[i - 1]] = 1;
    for (reg int s = 0 ; s < bin[K] ; s ++)
    {
        for (reg int i = 1 ; i <= K ; i ++)
        {
            if (!(s & bin[i - 1])) continue;
            if (!f[i][s]) continue;
            for (reg int j = 1 ; j <= K ; j ++)
            {
                if (s & bin[j - 1]) continue;
                if (G[pos[i]][pos[j]] >= cb[s]) f[j][s | bin[j - 1]] |= f[i][s];
            }
        }
    }
    int ans = 0;
    for (reg int s = 0 ; s < bin[K] ; s ++)
        for (reg int i = 1 ; i <= K ; i ++)
            if (s & bin[i - 1] and f[i][s]) ans = max(ans, min(G[pos[i]][1], cb[s]));
    cout << ans << endl;
    return 0;
}

 

posted @ 2018-10-15 20:25  zZhBr  阅读(168)  评论(0编辑  收藏  举报