• noip2009最优贸易(水晶球)


    题目:http://codevs.cn/problem/1173/  https://www.luogu.org/problemnew/show/P1073

    本来考虑缩点什么的,后来发现不用。

    只要记录一下从起点走到现在经过的最小值和从终点走到现在经过的最大值就行了。

    从终点走到现在就是记录一个反向边。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define ll long long
    using namespace std;
    const int N=1e5+5,M=5e5+5;
    int n,m,head1[N],xnt1,head2[N],xnt2;
    ll c[N],fn[N],fx[N],mx;
    bool vis1[N],vis2[N];
    struct Edge{
        int next,to;
        Edge(int n=0,int t=0):next(n),to(t) {}
    }edge1[M<<1],edge2[M<<1];
    void add(int x,int y)
    {
        edge1[++xnt1]=Edge(head1[x],y);head1[x]=xnt1;
        edge2[++xnt2]=Edge(head2[y],x);head2[y]=xnt2;
    }
    void read()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%lld",&c[i]);
        int x,y,z;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y);if(z==2)add(y,x);
        }
    }
    void dj1()
    {
        memset(fn,1,sizeof fn);
        priority_queue<pair<ll,int> > q;fn[1]=c[1];q.push(make_pair(fn[1],1));
        while(q.size())
        {
            int k=q.top().second;q.pop();
            while(vis1[k]&&q.size())k=q.top().second,q.pop();
            if(vis1[k])break;vis1[k]=1;
            for(int i=head1[k],v;i;i=edge1[i].next)
                if(min(fn[k],c[v=edge1[i].to])<fn[v])
                {
                    fn[v]=min(fn[k],c[v]);q.push(make_pair(fn[v],v));
                }
        }
    }
    void dj2()
    {
        priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > >q;
        fx[n]=c[n];q.push(make_pair(fx[n],n));
        while(q.size())
        {
            int k=q.top().second;q.pop();
            while(vis2[k]&&q.size())k=q.top().second,q.pop();
            if(vis2[k])break;vis2[k]=1;
            for(int i=head2[k],v;i;i=edge2[i].next)
                if(max(fx[k],c[v=edge2[i].to])>fx[v])
                {
                    fx[v]=max(fx[k],c[v]);q.push(make_pair(fx[v],v));
                }
        }
    }
    int main()
    {
        read();
        dj1();dj2();
        for(int i=1;i<=n;i++)
            if(vis1[i]&&vis2[i])
                mx=max(mx,fx[i]-fn[i]);
        printf("%lld",mx);
        return 0;
    }
  • 相关阅读:
    Java中的逆变与协变
    JAVA中使用DOM解析XML文件
    ReentrantLock的使用
    tomcat源码 Container
    tomcat源码 Connector
    tomcat源码 StandardService
    BlockingQueue队列
    tomcat源码 StandardServer
    tomcat源码 分析 Catalina
    tomcat整体架构
  • 原文地址:https://www.cnblogs.com/Narh/p/8932268.html
Copyright © 2020-2023  润新知