题目链接。
分析:
一开始以为简单的DFS,直接做,MLE了。
本体应该用最短路径(Dijkstra算法)做。
此题的关键在于等级限制的处理,采用枚举,即假设酋长等级为5,等级限制为2,那么需要枚举等级从3~5,4~6,5~7
从满足改等级范围的结点组成的子图中用Dijkstra来算出最短路径,最后求出最小值。
AC代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> using namespace std; const int maxn = 100+10; const int INF = (1<<29); int G[maxn][maxn], level[maxn], val[maxn], n, d[maxn]; bool lim[maxn]; int dijkstra() { bool vis[maxn]; memset(vis, false, sizeof(vis)); for(int i=1; i<=n; i++) d[i] = INF; d[1] = 0; for(int i=1; i<n; i++) { int m = INF, x; for(int y=1; y<=n; y++) if(!vis[y] && lim[y] && m >= d[y]) m = d[x=y]; vis[x] = true; for(int y=1; y<=n; y++) if(!vis[y] && lim[y] && d[y]>d[x]+G[x][y]) d[y] = d[x]+G[x][y]; } int ans = INF; for(int i=1; i<=n; i++) { d[i] += val[i]; ans = min(ans, d[i]); } return ans; } int main() { int p, l, x, t, v; int m; //freopen("my.txt", "r", stdin); while(scanf("%d%d", &m,&n) == 2) { for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { G[i][j] = INF; } } for(int i=1; i<=n; i++) { scanf("%d%d%d", &p, &l, &x); val[i] = p; level[i] = l; for(int j=0; j<x; j++) { scanf("%d%d", &t, &v); G[i][t] = v; } } int ans = INF; for(int i=0; i<=m; i++) { memset(lim, false, sizeof(lim)); for(int j=1; j<=n; j++) { if(level[j] >= level[1]-m+i && level[j] <= level[1]+i) lim[j] = true; } ans = min(ans, dijkstra()); } printf("%d ", ans); } return 0; }
MLE代码也贴下。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> using namespace std; const int maxn = 100+10; struct Edge { int nu, p, next; }ed[1000000]; struct node { int p, l; int next; }head[maxn]; int mem, m; void add(int u, int v, int p) { ed[mem].nu = v; ed[mem].p = p; ed[mem].next = head[u].next; head[u].next = mem++; }; int dfs(int u, int minv, int maxv) { int ans = head[u].p; for(int i=head[u].next; i != -1; i = ed[i].next) { int nmin = min(minv, head[ed[i].nu].l); int nmax = max(maxv, head[ed[i].nu].l); if(nmax - nmin > m) continue; if(ed[i].p >= ans) continue; ans = min(ans, ed[i].p + dfs(ed[i].nu, nmin, nmax)); } return ans; } int main() { int n; int p, l, x, nu; //freopen("my.txt", "r", stdin); while(scanf("%d%d", &m,&n) == 2) { mem = 0; for(int i=1; i<=n; i++) { scanf("%d%d%d", &p, &l, &x); head[i].p = p; head[i].l = l; head[i].next = -1; for(int j=0; j<x; j++) { scanf("%d%d", &nu, &p); add(i, nu, p); } } printf("%d ", dfs(1, head[1].l, head[1].l)); } return 0; }