HDU 4284
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4284
题意:
给一个图,n个点m条边,边有权值代表在两边通行的代价。
给定H个城市,每个城市有入门费Ci,入门后有Di收入。
现要求从城市1出发,最后也要返回城市1,H个城市均要遍历到,问能否全部遍历到。
思路:
状压DP。dp[i][j],i表示状态,j表示最后一次到达的位置。
比赛的时候一直在想网络流,还是图论不熟练啊~
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define inf (1000000000)
const int MAXN = 17;
int dp[1 << MAXN][MAXN];
int gra[105][105];
struct D
{
int u;
int c1, c2;
}d[MAXN];
void floyd(int n)
{
for(int k = 1 ; k <= n ; k++){
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= n ; j++)
gra[i][j] = min(gra[i][j], gra[i][k] + gra[k][j]);
}
}
for(int i = 1 ; i <= n ; i++)
gra[i][i] = 0;
}
void DP(int num, int M)
{
memset(dp, -1, sizeof(dp));
for(int i = 0 ; i < num ; i++){
if(M >= d[i].c1 + gra[1][d[i].u]){
dp[1 << i][i] = M - d[i].c1 - gra[1][d[i].u] + d[i].c2;
// printf("i = %d, dp = %d\n", i, M - d[i].c1 - gra[1][d[i].u] + d[i].c2);
}
}
for(int i = 0 ; i < (1 << num) ; i++){
for(int j = 0 ; j < num ; j++){
if(( (1 << j) & i) && dp[i][j] != -1){
// printf("i = %d, j = %d\n", i, j);
for(int k = 0 ; k < num ; k++){
if(!(i & (1 << k))){
int ts = (i | (1 << k));
int u1 = d[j].u, u2 = d[k].u;
if(dp[i][j] >= d[k].c1 + gra[u1][u2]){
dp[ts][k] = max(dp[ts][k], dp[i][j] - gra[u1][u2] - d[k].c1 + d[k].c2);
// printf("ts = %d, k = %d, dp = %d\n", ts, k, dp[ts][k]);
}
}
}
}
}
}
}
int main()
{
// freopen("1007.in", "r", stdin);
int n, m, M;
int t;
scanf("%d", &t);
while(t--){
scanf("%d%d%d", &n, &m, &M);
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= n ; j++){
gra[i][j] = inf;
if(i == j) gra[i][j] = 0;
}
}
int u, v, w;
for(int i = 0 ; i < m ; i++){
scanf("%d%d%d", &u, &v, &w);
gra[u][v] = min(gra[u][v], w);
gra[v][u] = min(gra[v][u], w);
}
floyd(n);
scanf("%d", &m);
for(int i = 0 ; i < m ; i++)
scanf("%d%d%d", &d[i].u, &d[i].c2, &d[i].c1);
DP(m, M);
int ans = -1;
for(int i = 0 ; i < m ; i++){
ans = max(ans, dp[(1 << m) - 1][i] - gra[1][d[i].u]);
// printf("i = %d, dp = %d\n", i, dp[(1 << m) - 1][i]);
}
if(ans >= 0)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}