题解:挖地雷


这道题可以看成是一个最长路,用拓扑+dp来解决。
如果从边上绕一个点到达目的地能挖到的地雷比直接过去挖到的地雷多,就选择从边上绕

代码:

#include <bits/stdc++.h>
using namespace std;
int head[1000001];
int a[1000001];
int n;
int ecnt = -1;
struct Edge {
    int to,nxt;
} e[10000001];
int path[1000001];
int ans = 0;
queue <int> q;
int dp[10000001];
int ru[10000001];
void addEdge(int x,int y) {
    e[++ecnt] = (Edge) {
	    y,head[x]
    };
    head[x] = ecnt;
}
void topo_sort() {
    for(int i = 1; i <= n; i++) {
	    if(ru[i] == 0) {
		    q.push(i);
	    }
	    dp[i] = a[i];
    }
    while(!q.empty()) {
	    int now = q.front();
	    q.pop();
	    for(int i = head[now]; ~i; i = e[i].nxt) {
		    int u = e[i].to;
		    if(a[u] + dp[now] > dp[u]) {
			    dp[u] = dp[now] + a[u];
			    path[u] = now;
		    }
		    if(!--ru[u]) {
			    q.push(u);
		    }
	    }
    }
}
int first = 1;
void print(int x) {
    if(path[x]) print(path[x]);
    if(first) first--;
    else printf("-");
    printf("%d" ,x);
}
int main() {
    scanf("%d" ,&n);
    memset(head,-1,sizeof(head));
    for(int i = 1; i <= n; i++) {
	    scanf("%d" ,&a[i]);
    }
    int id;
    while(1) {
	    int a,b;
	    scanf("%d %d" ,&a,&b);
	    if(a == 0 && b == 0) break;
	    addEdge(a,b);
	    ru[b]++;
    }
    topo_sort();
    int ans = 0;
    for(int i = 1; i <= n; i++) {
	    if(ans < dp[i]) {
		    ans = dp[i];
		    id = i;
	    }
}
    print(id);
    printf("\n%d\n" ,ans);
}
posted @ 2021-04-27 19:22  24Kmagic  阅读(98)  评论(0)    收藏  举报