本题正解是tarjan,我没有去写
用两次BFS,第一次BFS在原图的反图上做,从n开始,找到从n出发能够达到到达的所有点。
第二次BFS从起点开始,保存每个点到n点路径上面的最小值mp[i]。
最后遍历一遍,求出w[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 mp[MAXN],w[MAXN]; bool able[MAXN],vis[MAXN]; queue<int> myque; int n,m; void bfs1() { for(int i = 1; i <= n; i++)//vis[i]表示i是否在队列中,这样写可以避免图中环造成的影响 { myque.push(i); vis[i] = 1; } while(!myque.empty()) { int u = myque.front(); vis[u] = 0; myque.pop(); 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() { myque.push(n); able[n] = 1; while(!myque.empty()) { int u = myque.front(); myque.pop(); for(int i = head2[u]; i != -1; i = edge2[i].next) { int v = edge2[i].v; 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]); mp[i] = 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();//反向,找能到达的点 bfs1();//正向,找i到n路径上最大值 int ans = 0; for(int i = 1; i <= n; i++) if(able[i]) ans = max(ans,w[i]-mp[i]); printf("%d\n",ans); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-12-29 11:44:14