• Poj(1511),SPFA


    题目链接:http://poj.org/problem?id=1511

    嗯,最后一次写SPFA了,以后就套模板了。

    题意:给出n个点和n条有向边,求所有点到源点1的来回最短路之和(保证每个点都可以往返源点1).

    思路:建反图,从任意一点回来,就变成了反图上的从1到任意一点去。

    next记录前驱,head[u],记录u是在第几条边,然后往前扫。例如:edge[0].next = head[1] =0;head[1] = 0;edge[3].next = head[1] =0;head[1] =3;

    再扫的时候就是,3->0;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAXN 1000100
    #define inf 1LL<<60
    
    struct Edge
    {
        int v,w,next;
    } edge1[MAXN*10],edge2[MAXN*10];
    
    int cnt[MAXN];
    int head1[MAXN],head2[MAXN];
    long long dist[MAXN];
    bool mark[MAXN];
    int n,m,NE;
    
    void add(Edge *edge,int *head,int u,int v,int w)
    {
        edge[NE].v=v;
        edge[NE].w=w;
        edge[NE].next=head[u];  //边的前驱是head[u],之前的那条边
        head[u]=NE;     //head[u] 重新覆盖
    }
    
    
    long long SPFA(Edge *edge,int *head,int u)
    {
        memset(mark,false,sizeof(mark));
        memset(cnt,0,sizeof(cnt));
        
        for(int i=1; i<=n; i++)
            dist[i]=inf;
        dist[u]=0;
        mark[u] =true;
        queue<int>Q;
        Q.push(u);
        while(!Q.empty())
        {
            u=Q.front();
            Q.pop();
            mark[u]=false;
            for(int i=head[u]; i!=-1; i=edge[i].next)
            {
                int v=edge[i].v,w=edge[i].w;
                if(dist[u]+w<dist[v])
                {
                    dist[v]=dist[u]+w;
                    if(!mark[v])
                    {
                        mark[v]=true;
                        Q.push(v);
                        
                        /*if(++cnt[v]>n)
                            return false;*/
                    }
                }
            }
        }
        long long ans=0;
        for(int i=2; i<=n; i++)ans+=dist[i];
        return ans;
    }
    
    int main()
    {
        int _case,u,v,w;
        scanf("%d",&_case);
        while(_case--)
        {
            scanf("%d%d",&n,&m);
            NE=0;
            memset(head1,-1,(n+2)*sizeof(int));
            memset(head2,-1,(n+2)*sizeof(int));
            while(m--)
            {
                scanf("%d%d%d",&u,&v,&w);
                add(edge1,head1,u,v,w);
                add(edge2,head2,v,u,w);//建反图
                NE++;
            }
            printf("%lld
    ",SPFA(edge1,head1,1)+SPFA(edge2,head2,1));
        }
        return 0;
    }
  • 相关阅读:
    css取消input、select默认样式(手机端)
    Vue解决sass-loader的版本过高导致的编译错误
    在Vue项目中引入element-ui,显示结果没有样式的问题
    修改Vue项目打开指定浏览器和修改端口号
    Vue如何关闭eslint
    停止事件冒泡
    子组件中定义的方法如何传给父组件调用了呢?
    vue自定义时间过滤器之使用date-fans代替moment
    面试5(每日打卡)
    2019.10.22
  • 原文地址:https://www.cnblogs.com/TreeDream/p/5738381.html
Copyright © 2020-2023  润新知