• 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;
    }
    
  • 相关阅读:
    正则表达式收藏
    c#mvc实现登录
    jQuery获取URL中的参数
    TortoiseSVN新人使用指南
    CheckBox获取一组及全选
    day45
    day44
    day43
    day43
    day42
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11416583.html
Copyright © 2020-2023  润新知