zoukankan      html  css  js  c++  java
  • AcWing383 观光(最短路+拓扑序)

    这题和最短路计数差不多,只是多了个次短路判断,其实也是跟最短路一样是满足拓扑序的,也就是说不可能出队之后绕一个环回来次短路还变化了

    因此也可以用迪杰斯特拉这种天然满足拓扑序的进行更新,只不过需要注意一下最短路和次短路的变化

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e4+10;
    int n,m;
    int h[N],ne[N],e[N],idx,w[N];
    int dis[N][2];
    int cnt[N][2];
    int st[N][2];
    void add(int a,int b,int c){
        e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
    }
    struct node{
        int d,type,id;
        bool operator > (const node &t) const{
            return d>t.d;
        }
    };
    void dij(int S){
        memset(dis,0x3f,sizeof dis);
        memset(st,0,sizeof st);
        memset(cnt,0,sizeof cnt);
        priority_queue<node,vector<node>,greater<node> > q;
        dis[S][0]=0;
        cnt[S][0]=1;
        q.push({0,0,S});
        while(q.size()){
            auto t=q.top();
            q.pop();
            int ver=t.id;
            int sign=t.type;
            if(st[ver][sign])
            continue;
            st[ver][sign]=1;
            int i;
            for(i=h[ver];i!=-1;i=ne[i]){
                int j=e[i];
                if(dis[j][0]>dis[ver][sign]+w[i]){
                    dis[j][1]=dis[j][0],cnt[j][1]=cnt[j][0];
                    q.push({dis[j][1],1,j});
                    dis[j][0]=dis[ver][sign]+w[i];
                    cnt[j][0]=cnt[ver][sign];
                    q.push({dis[j][0],0,j});
                }
                else if(dis[j][0]==dis[ver][sign]+w[i]){
                    cnt[j][0]+=cnt[ver][sign];
                }
                else if(dis[j][1]>dis[ver][sign]+w[i]){
                    dis[j][1]=dis[ver][sign]+w[i];
                    cnt[j][1]=cnt[ver][sign];
                    q.push({dis[j][1],1,j});
                }
                else if(dis[j][1]==dis[ver][sign]+w[i]){
                    cnt[j][1]+=cnt[ver][sign];
                }
            }
        }
    }
    int main(){
        int t;
        cin>>t;
        while(t--){
            cin>>n>>m;
            int i;
            memset(h,-1,sizeof h);
            idx=0;
            for(i=1;i<=m;i++){
                int a,b,c;
                cin>>a>>b>>c;
                add(a,b,c);
            }
            int S,T;
            cin>>S>>T;
            dij(S);
            int ans=cnt[T][0];
            if(dis[T][0]==dis[T][1]-1)
            ans+=cnt[T][1];
            cout<<ans<<endl;
        }
    }
    View Code
  • 相关阅读:
    RAISERROR (Transact-SQL)的用法
    Eclipse 工程中set() get()等方法报错的解决方法
    SqlServer单步调试
    centOS7 查看防火墙状态
    如何查看Linux端口占用情况
    异常处理机制(Begin try Begin Catch)
    inner join 、left join 、right join 和full join的区别
    Emacs 快速指南
    x01.DiamondIDE: hello ide
    剑指offer大总结
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12827724.html
Copyright © 2011-2022 走看看