洛谷P3008 [USACO11JAN]道路和飞机Roads and Planes

第一直觉是tarjan缩点+拓扑,但是不知道如何下手(据说正解就是这个)

然后画了个图,发现,好像是个单源最短路!因为有单向边,所以一些点去不了,所以输出判dis就行

然后!!!它TLE了!!!

加优化,SLF和LLL优化,专氪网格图

代码

//By AcerMo
#include<cmath>
#include<deque>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=30050;
struct edge{int to,cost;}add;
vector<edge>v[M];
int n,m1,m2,st;
int dis[M],vis[M];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch>'9'||ch<'0') {if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline void SPFA()
{
    fill(dis,dis+n+1,M*30);  
    deque<int>q;dis[st]=0;q.push_front(st);  
    while (q.size())  
    {  
        int u=q.front();q.pop_front();vis[u]=0;  
        for (int i=0;i<v[u].size();i++)  
        {  
            int go=v[u][i].to;  
            int pay=v[u][i].cost;  
            if (dis[go]>dis[u]+pay)  
            {  
                dis[go]=dis[u]+pay;  
                if (!vis[go])  
                {  
                    if (q.empty()||dis[go]>dis[q.front()]) q.push_back(go),vis[go]=1;
                    else q.push_front(go),vis[go]=1;  
                }  
            }  
        }  
    }  
	return ;
}
signed main()
{
	n=read();m1=read();m2=read();st=read();
	for (int i=1;i<=m1;i++)
	{
		int x=read(),y=read(),z=read();
		add.to=y;add.cost=z;v[x].push_back(add);
		add.to=x;add.cost=z;v[y].push_back(add);
	}
	for (int i=1;i<=m2;i++)
	{
		int x=read();add.to=read();add.cost=read();v[x].push_back(add);
	}
	SPFA();
	for (int i=1;i<=n;i++)
	if (dis[i]<M*30) cout<<dis[i]<<endl;
	else puts("NO PATH"); 	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ACerAndAKer/article/details/81434166