[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
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; }