P3008 [USACO11JAN]Roads and Planes G (最短路)

不要问我为啥不加天数了,问就是数不过来了

题目大意

Farmer John 正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到 T个城镇 ,编号为 1到T 。这些城镇之间通过R 条道路(编号为1 到 R)和 条航线(编号为 1到 P)连接。每条道路 i或者航线i 连接城镇Ai 到 Bi,花费为Ci 。

对于道路0<=Ci<=104,然而航线的花费很神奇,花费Ci可能是负数。道路是双向的,可以从Ai到Bi,也可以从Bi到Ai,话费都是Ci,然而航线与之不同,只可以Ai到Bi。

事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策保证:如果有一条航线可以从Ai到Bi,那么保证不可能通过一些道路和航线从Bi回到Ai。由于 FJ 的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇S把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。

输入格式

第一行为四个空格隔开的整数:T,R,P,S;

第二到第R+1行:三个空格隔开的整数(表示一条道路):Ai,Bi和Ci;

第R+2到R+P+1行:三个空格隔开的整数(表示一条航线):Ai,Bi和Ci。

输出格式

输出T行,第i行表示到达城镇i的最小花费,如果不存在输出NO PATH。

样例

样例输入

6 3 3 4 
1 2 5 
3 4 5 
5 6 10 
3 5 -100 
4 6 -100 
1 3 -10 

样例输出

NO PATH 
NO PATH 
5 
0 
-95 
-100 

数据范围与提示

对于全部数据,1<=T<=2.5×104,1<=R,P<=5×104,1<=Ai,Bi,S<=T,保证对于所有的道路,0<=Ci<=104,对于所有的航线,-104<=Ci<=104.

算法分析:

  • 这题再看不出来是SPFA就该吃**了
  • 但是挂了
  • 这个题用SPFA会T掉 (加上队列优化一样会T掉) , 所以我们需要别的优化:STL
  • STL主要利用双端队列优化

代码展示

//不加STL优化会T到88分 加STL会不会T主要看脸………… 建议交之前洗把脸 (如果一次T了就多交两次) 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int head[maxn],cnt;
int dis[maxn],vis[maxn];

struct node{
	int next,to,dis;
}a[maxn];

void add(register int x,int y,int z){
	a[++cnt].to = y;
	a[cnt].dis = z;
	a[cnt].next = head[x];
	head[x] = cnt;
}

int read(){
    char ch=getchar();int ans=0,p=1;
    while(ch>'9'||ch<'0'){
        if(ch=='-') p=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0'){
        ans=(ans<<1)+(ans<<3)+ch-'0';
        ch=getchar();
    }
    return ans*p;
}

void spfa(register int x){
    memset(dis,0x3f,sizeof(dis));
    deque<int> q;q.push_back(x),dis[x]=0;//双端队列
    while(!q.empty())
    {
        int now=q.front();q.pop_front();
        vis[now]=0;
        for(register int i=head[now];i;i=a[i].next)
        {
            int v=a[i].to;
            if(dis[v]>dis[now]+a[i].dis)
            {
                dis[v]=dis[now]+a[i].dis;
                if(!vis[v])
                {
                    vis[v]=1;
                    if(!q.empty()&&dis[v]<dis[q.front()]) q.push_front(v);//双端队列优化 将距离最小的放在队首(优化效果有点玄学 但是平均优化在15% ~ 20%之间)
                    else q.push_back(v);
                }
            }
        }
    }
}

int main(){
	int n = read(),r = read(),p = read(),s = read();
	for(register int i = 1;i <= r;++i){
		int x = read(),y = read(),w = read();
		add(x,y,w);
		add(y,x,w);
	}
	for(register int i = 1;i <= p;++i){
		int x = read(),y = read(),w = read();;
		add(x,y,w);
	}
	spfa(s);
	for(register int i = 1;i <= n;++i){
		if(dis[i] == 0x3f3f3f3f){printf("NO PATH\n");continue;}
		printf("%d\n",dis[i]);
	}
	return 0;
}

附: 竞赛SPFA常用STL优化 不仅好写而且优化效果比较明显 还有第二种优化是LLL 但是竞赛中不常用(不好写) 可以自行百度扩展 (STL + LLL俩一起用大概优化在50%左右)

posted @ 2020-07-10 09:00  HISKrrr  阅读(122)  评论(0编辑  收藏  举报