NOIP2009 最优贸易(BFS)

本题正解是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 */



原文地址:https://www.cnblogs.com/brucemengbm/p/7028039.html