zoukankan      html  css  js  c++  java
  • Gym

    题意:给定N点M边的有向图,每条边有距离和颜色,一条有效路径上不能有相邻的边颜色相同。现在给定起点S,多次讯问S到点X的最短有效距离。

    TLE思路:用二维状态dis(u,c)表示起点到u,最后一条边的颜色是c的最短距离,用map解决了二维空间不足的问题。但是T第151个点。所以需要优化,标解的优化是把dis(u,c)改为dis(u,0)或者dis(u,1)分别表示颜色同和不同的最短距离。

    其他思路:用边表示通过那条边到点的最短距离。由于边自带颜色属性,所以就不需要其他状态了。这个方法比较直观,可以直接看代码。

    TLE代码:(加了优化也不行。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define ll long long
    #define pii pair<int,int>
    #define mp make_pair
    #define Fi first
    #define Se second
    using namespace std;
    const int maxn=200010;
    const ll inf=1LL<<60;
    int Laxt[maxn],Next[maxn],To[maxn],W[maxn],C[maxn];
    int S,N,cnt; ll ans[maxn];
    deque<pii>q;
    map<int,ll>dis[maxn];
    map<int,int>vis[maxn];
    void add(int u,int v,int w,int c){
        Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v; W[cnt]=w; C[cnt]=c;
    }
    void spfa()
    {
        rep(i,1,N) ans[i]=inf; ans[S]=0;
        for(int i=Laxt[S];i;i=Next[i]){
            dis[To[i]][C[i]]=W[i]; ans[To[i]]=W[i]; 
            vis[To[i]][C[i]]=1; 
            if(!q.empty()&&dis[To[i]][C[i]]<dis[q.front().Fi][q.front().Se]) 
            q.push_front(mp(To[i],C[i]));
            else q.push_back(mp(To[i],C[i]));
        }
        while(!q.empty()){
            pii H=q.front(); q.pop_front();
            int u=H.Fi,c=H.Se; ll tdis=dis[u][c]; vis[u][c]=0;
            for(int i=Laxt[u];i;i=Next[i]){
                int v=To[i];
                if(c==C[i]) continue;
                if(dis[v].find(C[i])==dis[v].end()){
                    dis[v][C[i]]=tdis+W[i];
                    ans[v]=min(ans[v],dis[v][C[i]]);
                    if(!vis[v][C[i]]){
                         vis[v][C[i]]=1; 
                         if(!q.empty()&&dis[v][C[i]]<dis[q.front().Fi][q.front().Se]) q.push_front(mp(v,C[i]));
                         else q.push_back(mp(v,C[i]));
                    }
                }
                else if(tdis+W[i]<dis[v][C[i]]){
                    dis[v][C[i]]=tdis+W[i];
                    ans[v]=min(ans[v],dis[v][C[i]]);
                    if(!vis[v][C[i]]){
                         vis[v][C[i]]=1; 
                         if(!q.empty()&&dis[v][C[i]]<dis[q.front().Fi][q.front().Se]) q.push_front(mp(v,C[i]));
                         else q.push_back(mp(v,C[i]));
                    }
                }
            }
        }
        rep(i,1,N) if(ans[i]==inf) ans[i]=-1;
    }
    int main()
    {
        int M,CC,Q,u,v,w,c;
        scanf("%d%d%d",&N,&M,&CC);
        rep(i,1,M){
            scanf("%d%d%d%d",&u,&v,&w,&c);
            add(u,v,w,c);
        }
        scanf("%d%d",&S,&Q);
        spfa();
        while(Q--){
            scanf("%d",&u);
            printf("%I64d
    ",ans[u]);
        }
        return 0;
    }
    View Code

    AC代码:

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define ll long long
    using namespace std;
    const int maxn=200010;
    const ll inf=1LL<<60;
    int Laxt[maxn],Next[maxn],To[maxn],W[maxn],C[maxn];
    int S,N,cnt,vis[maxn]; ll ans[maxn],dis[maxn];
    void add(int u,int v,int w,int c){
        Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v; W[cnt]=w; C[cnt]=c;
    }
    void spfa()
    {
        deque<int>q;
        rep(i,1,N) ans[i]=inf; ans[S]=0;
        rep(i,1,cnt) dis[i]=inf; 
        for(int i=Laxt[S];i;i=Next[i]){
            dis[i]=W[i]; q.push_back(i); vis[i]=1;
        }
        while(!q.empty()){
            int u=q.front();  q.pop_front(); vis[u]=0;
            for(int i=Laxt[To[u]];i;i=Next[i]){
                if(C[u]!=C[i]){
                    if(dis[i]>dis[u]+W[i]){
                        dis[i]=dis[u]+W[i];
                        if(!vis[i]) {
                            vis[i]=1;
                            if(!q.empty()&&dis[i]<dis[q.front()]) q.push_front(i); //注意不要为空 
                            else q.push_back(i);
                        }
                    }
                }
            }
        }
        rep(i,1,cnt) ans[To[i]]=min(ans[To[i]],dis[i]);
        rep(i,1,N) if(ans[i]==inf) ans[i]=-1;
    }
    int main()
    {
        int M,CC,Q,u,v,w,c;
        scanf("%d%d%d",&N,&M,&CC);
        rep(i,1,M){
            scanf("%d%d%d%d",&u,&v,&w,&c);
            add(u,v,w,c);
        }
        scanf("%d%d",&S,&Q);
        spfa();
        while(Q--){
            scanf("%d",&u);
            printf("%I64d
    ",ans[u]);
        }
        return 0;
    }
  • 相关阅读:
    安卓长按应用图标弹出快捷方式(shortcut)
    网站主题变暗黑,快速解决
    android 11适配的其他注意点
    vue cli3.0构建多页面应用
    Alibaba Canal config 漏洞验证
    检测magiskhide
    Flutter垃圾回收器
    UIbutton 在动画过程中也能响应事件,主要利用layer的hitTest方法
    CocoaPods 私有化
    Android WorkManager使用入门
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9507189.html
Copyright © 2011-2022 走看看