• [Luogu1821][USACO07FEB]银牛派对Silver Cow Party


    由题意可知,我们需要求的是很多个点到同一个店的最短距离,然后再求同一个点到很多个点的最短距离。
    对于后者我们很好解决,就是很经典的单源最短路径,跑一边dijkstra或者SPFA即可。
    然而对于前者,我们应该怎么解决呢?难道我们需要求一边Floyd?当然不可能!(O(n^3))的时间复杂度,对于我们的(n<=1000)是果断要超时的。
    深入分析,对于一张图,A到B的最短距离,应该等于B到A,在反转一张图以后的最短距离。所谓反转一张图,就是把变得方向调转。这一点是很显然的!
    因此,对于问题一,我们只需要把图反转,然后求那个点到其它的最短距离即可。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define rep(i,a,n) for(register int i=(a);i<=(n);++i)
    #define per(i,a,n) for(register int i=(a);i>=(n);--i)
    #define fec(i,x) for(register int i=head[x];i;i=Next[i])
    #define debug(x) printf("debug:%s=%d
    ",#x,x)
    #define mem(a,x) memset(a,x,sizeof(a))
    template<typename A>inline void read(A&a){a=0;A f=1;int c=0;while(c<'0'||c>'9'){c=getchar();if(c=='-')f*=-1;}while(c>='0'&&c<='9'){a=a*10+c-'0';c=getchar();}a*=f;}
    template<typename A,typename B>inline void read(A&a,B&b){read(a);read(b);}
    template<typename A,typename B,typename C>inline void read(A&a,B&b,C&c){read(a);read(b);read(c);}
    
    const int maxn=1000+7,maxm=100000+7,INF=0x7f7f7f7f; 
    int u[maxm],v[maxm],w[maxm],Next[maxm],head[maxn],tot;
    int u2[maxm],v2[maxm],w2[maxm],Next2[maxm],head2[maxn],tot2;
    int n,m,p,x,y,z,ans;
    int dist1[maxn],dist2[maxn];
    bool visit[maxn];
    
    inline void addedge(int x,int y,int z){
    	u[++tot]=x;v[tot]=y;w[tot]=z;
    	Next[tot]=head[x];head[x]=tot;
    }
    inline void addedge2(int x,int y,int z){
    	u2[++tot2]=x;v2[tot2]=y;w2[tot2]=z;
    	Next2[tot2]=head2[x];head2[x]=tot2;
    }
    
    void Dijkstra(int *u,int *v,int *w,int *head,int *Next,int *dist,int s){
    	mem(visit,0);dist[s]=0;
    	rep(i,1,n){
    		int Min=INF,x;
    		rep(i,1,n)if(!visit[i]&&dist[i]<Min)Min=dist[i],x=i;
    		visit[x]=1;
    		fec(i,x)if(!visit[v[i]]&&dist[v[i]]>dist[x]+w[i])dist[v[i]]=dist[x]+w[i];
    	}
    }
    
    void Init(){
    	read(n,m,p);
    	rep(i,1,m){
    		read(x,y,z);
    		addedge(x,y,z);
    		addedge2(y,x,z); 
    	}
    }
    
    void Work(){
    	mem(dist1,0x7f);mem(dist2,0x7f);
    	Dijkstra(u,v,w,head,Next,dist1,p);
    	Dijkstra(u2,v2,w2,head2,Next2,dist2,p);
    	rep(i,1,n)ans=max(ans,dist1[i]+dist2[i]);
    	printf("%d
    ",ans); 
    }
    
    int main(){
    	Init();
    	Work();
    	return 0;
    }
    
  • 相关阅读:
    【win10系统问题】远程桌面登录一次后,第二次登录看不到用户名和密码输入框
    如何更改Arcmap里经纬度小数点后面的位数?
    腾讯视频qlv格式转换MP4普通视频方法
    kettle_Spoon 修改共享DB连接带汉字引发的错误
    AutoCAD2015激活码和密钥
    SQL获取本周,上周,本月,上月第一天和最后一天[注:本周从周一到周天]
    SQL语句 不足位数补0
    c# winform 服务器提交了协议冲突. Section=ResponseStatusLine
    java.net.ProtocolException: Server redirected too many times
    MarkDown空格缩进的方法
  • 原文地址:https://www.cnblogs.com/hankeke/p/USACO07FEB-Silver_Cow_Party.html
Copyright © 2020-2023  润新知