zoukankan      html  css  js  c++  java
  • POJ

    这道题也算是一道模板题,但是第一次用优先队列迪杰斯特拉就T了。1e6的数据量,给了8s,网上其他题解中说要用SPFA。

    题意:N个点的带权有向图。每次都从1出发,要到达其余没有被访问过的一个点(发传单?),然后返回,过程中其余被访问的点不计算在内。求整个过程走过的最短路程。

    分析:用原图跑SPFA计算从源点1到其余各点的最短路,再将原图转置为反向图,对反向图再跑一遍SPFA,计算出各点到1的最短路(求各点到一个点的最短路是这么个操作)。

    然后求sigma(d[i]+rd[i])。

    #include<iostream>
    #include<cstring>
    #include<stdio.h>
    #include<map>
    #include<string>
    #include<algorithm>
    #include<queue>
    //#define LOCAL
    using namespace std;
    typedef long long LL;
    const LL INF =(1ll<<60);
    const int maxn =1e6+5;
    
    struct Edge{
        int to,next;
        LL val;
    };
    
    struct SPFA{
        int head[maxn];
        Edge edges[maxn];
        LL d[maxn];
        bool inq[maxn];
        int n,tot;
        
        void init(int n){
            this->tot=0;
            this->n = n;
            memset(head,-1,sizeof(head));
        }
        void AddEdge(int u,int v,LL val){
            edges[tot].to = v;
            edges[tot].val = val;
            edges[tot].next = head[u];
            head[u] = tot++;
        }
    
        void spfa(int s){
            for(int i=0;i<=n;++i){
                inq[i]=false;
                d[i] = INF;
            }
            queue<int> Q;
            Q.push(s);
            d[s]=0; inq[s] = true;
            while(!Q.empty()){
                int x = Q.front();Q.pop();
                inq[x] =false;
                for(int i = head[x];~i;i=edges[i].next){
                    int v = edges[i].to;
                    if(d[v]>d[x]+edges[i].val){
                        d[v] = d[x]+edges[i].val;
                        if(!inq[v]){
                            Q.push(v);
                            inq[v] = true;
                        }
                    }
                }
            }
        }
    }G,rG;
    
    int main()
    {
        #ifdef LOCAL
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
           #endif
        int N,M,u,v;
        LL tmp;
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&N,&M);
            G.init(N);
            rG.init(N);
            for(int i=1;i<=M;++i){
                scanf("%d%d%lld",&u,&v,&tmp);
                G.AddEdge(u,v,tmp);
                rG.AddEdge(v,u,tmp);
            }
            G.spfa(1);
            rG.spfa(1);
            LL res=0;
            for(int i=2;i<=N;++i){
                res+=G.d[i]+rG.d[i];
            }
            printf("%lld
    ",res);
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    Java实现连接FTP服务并传递文件
    消息队列(MQ)入门-activemq,rocketmq代码级别
    js分页功能实现
    记录几个遇到的问题和解决方法
    oracle 日志归档设置
    打印系统时间
    linux 定时任务
    linux 安装jdk
    db2 命令
    二维码、条形码扫描——使用Google ZXing
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9311220.html
Copyright © 2011-2022 走看看