zoukankan      html  css  js  c++  java
  • yzoj P1412 & 洛谷P1629 邮递员送信 题解

    有一个邮递员要送东西,邮局在结点1。他总共要送N-1样东西,其目的地分别是2~N。由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条道路需要一定的时间。这个邮递员每次只能带一样东西。求送完这N-1样东西并且最终回到邮局最少需要多少时间。

    很容易发现我们要求 (sum_{j=1}^n) dis[1][ j ]+dis[ j ][1],可以想到跑spfa,对于dis[1][ j ]可以一遍spfa解决但是对于 dis[ j ][1]却不好解决,如果跑n遍spfa明显超时,但我们可以换个思路,建立反图,对节点1跑spfa,那么1节点到别的点的距离就是别的点到1节点的距离。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    const int N=1010,M=100010;
    int head[N][2],ver[M][2],edge[M][2],Next[M][2],d[N][2];
    int n,m,tot1,tot2;
    long long ans;
    bool v[N];
    queue<int> q;
    void add(int x,int y,int z){
    	ver[++tot1][0]=y;edge[tot1][0]=z;Next[tot1][0]=head[x][0],head[x][0]=tot1;
    }
    void add1(int x,int y,int z){
    	ver[++tot2][1]=y;edge[tot2][1]=z;Next[tot2][1]=head[x][1],head[x][1]=tot2;
    }
    void spfa(){
    	memset(d,0x3f,sizeof(d));
    	d[1][0]=0,v[1]=1;
    	q.push(1);
    	while(q.size()){
    		int x=q.front();q.pop();
    		v[x]=0;
    		for(int i=head[x][0];i;i=Next[i][0]){
    			int y=ver[i][0],z=edge[i][0];
    			if(d[y][0]>d[x][0]+z){
    				d[y][0]=d[x][0]+z;
    				if(!v[y]) q.push(y),v[y]=1;
    			}
    		}
    	}
    	while(!q.empty()) q.pop();
    	memset(v,0,sizeof(v));
    	d[1][1]=0,v[1]=1;
    	q.push(1);
    	while(q.size()){
    		int x=q.front();q.pop();
    		v[x]=0;
    		for(int i=head[x][1];i;i=Next[i][1]){
    			int y=ver[i][1],z=edge[i][1];
    			if(d[y][1]>d[x][1]+z){
    				d[y][1]=d[x][1]+z;
    				if(!v[y]) q.push(y),v[y]=1;
    			}
    		}
    	}
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=m;++i){
    		int x,y,z;
    		x=read();y=read();z=read();
    		add(x,y,z);
    		add1(y,x,z);
    	}
    	spfa();
    	for(int i=1;i<=n;++i){
    		ans+=d[i][0]+d[i][1];
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    LeetCode 1122. Relative Sort Array (数组的相对排序)
    LeetCode 46. Permutations (全排列)
    LeetCode 47. Permutations II (全排列 II)
    LeetCode 77. Combinations (组合)
    LeetCode 1005. Maximize Sum Of Array After K Negations (K 次取反后最大化的数组和)
    LeetCode 922. Sort Array By Parity II (按奇偶排序数组 II)
    LeetCode 1219. Path with Maximum Gold (黄金矿工)
    LeetCode 1029. Two City Scheduling (两地调度)
    LeetCode 392. Is Subsequence (判断子序列)
    写程序判断系统是大端序还是小端序
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11416583.html
Copyright © 2011-2022 走看看