本题正解是tarjan。我没有去写
之前的代码是错误的不好意思,因为数据太弱一直没有发现。
相同还是两遍bfs,一次正向,一次反向。在正向的时候我们求出从起点走到各个点的最小值。在反向的时候求出从终点走向起点的最大值。
这样一来,便能够知道对于每个点i。在1到n的路径上面,经过的最大值是多少。经过的最小值是多少。最后max(mx[i]-mp[i])就是要求的答案。
#include<cstdio> #include<iostream> #include<queue> #include<cstring> #define MAXN 100005 using namespace std; struct T { int v; int next; }edge[500005],edge2[500005]; int cnt,cnt2; int head[MAXN],head2[MAXN]; void add_edge(int u,int v) { edge[cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt++; } void add_edge2(int u,int v) { edge2[cnt2].v = v; edge2[cnt2].next = head2[u]; head2[u] = cnt2++; } int mx[MAXN],mp[MAXN],w[MAXN]; bool able[MAXN],vis[MAXN]; int n,m; void bfs1() { memset(mp,0x3f,sizeof mp); queue<int> myque; myque.push(1); vis[1] = 1; while(!myque.empty()) { int u = myque.front(); vis[u] = 0; myque.pop(); mp[u] = min(mp[u],w[u]); for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(mp[v] > mp[u]) { mp[v] = mp[u]; if(!vis[v]) { vis[v] = 1; myque.push(v); } } } } } void bfs2() { memset(mx,0,sizeof mx); queue<int> myque; myque.push(n); able[n] = 1; while(!myque.empty()) { int u = myque.front(); able[u] = 0; myque.pop(); mx[u] = max(mx[u],w[u]); for(int i = head2[u]; i != -1; i = edge2[i].next) { int v = edge2[i].v; if(mx[v] < mx[u]) { mx[v] = mx[u]; if(!able[v]) { able[v] = 1; myque.push(v); } } } } } int main() { memset(head,-1,sizeof head); memset(head2,-1,sizeof head2); scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++) scanf("%d",&w[i]); for(int i = 1; i <= m; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add_edge(x,y); add_edge2(y,x); if(z == 2) { add_edge(y,x); add_edge2(x,y); } } bfs2();//反向,找n到i路径上的最大值 bfs1();//正向,找1到i路径上的最小值 int ans = 0; for(int i = 1; i <= n; i++) ans = max(ans,mx[i]-mp[i]); printf("%d ",ans); return 0; } /*4 3 10 10 1 10 1 2 1 2 4 1 3 2 1 */