本题正解是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;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/cqbzwja/article/details/47405497