题目背景
最短路模板题目。SPFA 或 用堆优化的迪杰斯特拉算法均可实现。
题目描述
成都浣花溪公园是一座有着诗歌文化气息的公园,它以杜甫草堂的历史文化内涵为背景,运用现代园林和建筑设计的前沿理论,以自然雅致的景观和建筑凸现川西文化醇厚的历史底蕴,是一座集将自然景观和城市景观、古典园林和现代建筑艺术有机结合的城市公园。
周末,Mr.Zeng和他儿子在浣花溪公园“诗歌大道”上欣赏诗歌,刚诗兴正浓,Mr.Zeng忽然想起汽车的车门没锁,于是他们要在最快的时间内走出公园赶到公园门口停车场。我们把公园的景点用数字标号(从1 到 N-1),在两个景点中之间会有道路连接,并且Mr.Zeng和他儿子都是素质很高的人,他们不会穿越公园的草坪,只会沿着公园的小路行走。Mr.Zeng想知道从他们当前所处的位置 S 到公园的出口(标号固定为 N)所需要的最短时间。你能帮帮他吗?
输入格式
输入文件的第一行有3 个正整数:N、K、T 并且用空格隔开,分别表示公园景点数目、公园小路条数,以及他们当前所处的景点编号。
接下来 K 行,每行三个整数,表示小路连接的两个景点的编号以及走过这条小路所需要的时间。
输出格式
一个整数,表示他们走出公园所需要的最短时间。
样例数据
输入
3 2 1
1 2 3
2 3 4
输出
7
备注
【数据范围】
对于 60% 的数据,保证 N<=1000,K<=10000。
对于 100% 的数据,保证 N<=10000,K<=100000。
对于 100% 的数据,保证结果在
231
内。
分析: Dijkstra+堆/SPFA/Dijkstra+优先队列模板
代码:
Dijkstra+堆(多半是废了)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
int getint()
{
int i = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1; ch = getchar();
}
while(ch >= '0' && ch <= '9') {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}
struct node
{
int w;
int num;
};
int n,k,x,y,i,j,tot,cnt,z,p,t;
int nxt[200100],w[200100],v[200100];
int pl[10010],first[10010];
int dis[10010];
node heap[10010];
void add(int x,int y,int z)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
v[tot]=y;
w[tot]=z;
}
void up(int x)
{
int j;
j=x>>1;
while(j!=0&&heap[x].w<heap[j].w)
{
swap(heap[x],heap[j]);
pl[heap[x].num]=x;
pl[heap[j].num]=j;
x=j;
j=j>>1;
}
}
void down(int x)
{
int j;
j=x<<1;
while(j<=cnt)
{
if(j<cnt&&heap[j].w>heap[j+1].w)
j++;
if(heap[x].w<heap[j].w)
break;
else
{
swap(heap[x],heap[j]);
pl[heap[x].num]=x;
pl[heap[j].num]=j;
x=j;
j=j<<1;
}
}
}
int main()
{
freopen("hhxgy.in","r",stdin);
freopen("hhxgy.out","w",stdout);
n=getint();k=getint();t=getint();
for(int i=1;i<=k;++i)
{
x=getint();y=getint();z=getint();
add(x,y,z);
add(y,x,z);
}
memset(dis,127,sizeof(dis));
dis[t]=0;
for(int i=1;i<=n;++i)
{
heap[i].w=1E+9;
heap[i].num=i;
pl[i]=i;
}
cnt=n;
heap[pl[t]].w=0;
up(pl[t]);
for(int i=1;i<=n;++i)
{
j=heap[1].num;
heap[1]=heap[cnt];
cnt--;
down(1);
p=first[j];
while(p>0)
{
if(dis[j]+w[p]<dis[v[p]])
{
dis[v[p]]=dis[j]+w[p];
heap[pl[v[p]]].w=dis[v[p]];
up(pl[v[p]]);
}
p=nxt[p];
}
}
cout<<dis[n]<<endl;
return 0;
}
SPFA
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;isdigit(ch);ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}
const int maxn=10010;
const int maxk=100010;
int n,k,t,x,y,z;
int tot,first[maxn],nxt[maxk*2],to[maxk*2],w[maxk*2];//双向边注意数组大小*2
int dis[maxn];
bool visit[maxn];
queue<int> que;
void addedge(int x,int y,int z)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
to[tot]=y;
w[tot]=z;
tot++;
nxt[tot]=first[y];
first[y]=tot;
to[tot]=x;
w[tot]=z;
}
void SPFA()
{
memset(dis,0x3f3f3f3f,sizeof(dis));//记得给dis赋一个极大初值(但是不要用127,因为dis[u]+w[p]的时候可能会爆int)
dis[t]=0;
que.push(t);
visit[t]=true;
while(!que.empty())
{
int u=que.front();
que.pop();
visit[u]=false;//记得出栈
for(int p=first[u];p;p=nxt[p])
{
int v=to[p];
if(dis[v]>dis[u]+w[p])
{
dis[v]=dis[u]+w[p];
if(!visit[v])//记得判断v是否在栈中
que.push(v);
}
}
}
}
int main()
{
freopen("park.in","r",stdin);
freopen("park.out","w",stdout);
n=getint(),k=getint(),t=getint();
for(int i=1;i<=k;++i)
{
x=getint(),y=getint(),z=getint();
addedge(x,y,z);
}
SPFA();
cout<<dis[n]<<'\n';
return 0;
}
Dijkstra+优先队列
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;isdigit(ch);ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}
const int maxn=10010;
const int maxk=100010;
int n,k,t,x,y,z;
int tot,first[maxn],nxt[maxk*2],to[maxk*2],w[maxk*2];//双向边注意数组大小*2
int dis[maxn];
priority_queue<pair<int,int> > que;
void addedge(int x,int y,int z)
{
tot++;
nxt[tot]=first[x];
first[x]=tot;
to[tot]=y;
w[tot]=z;
tot++;
nxt[tot]=first[y];
first[y]=tot;
to[tot]=x;
w[tot]=z;
}
void dijkstra()
{
memset(dis,0x3f3f3f3f,sizeof(dis));//记得给dis赋一个极大初值(但是不要用127,因为dis[u]+w[p]的时候可能会爆int)
dis[t]=0;
que.push(make_pair(0,t));
while(!que.empty())
{
int u=que.top().second;//普通队列是que.front(),优先队列是que.top()
que.pop();
for(int p=first[u];p;p=nxt[p])
{
int v=to[p];
if(dis[v]>dis[u]+w[p])
{
dis[v]=dis[u]+w[p];
que.push(make_pair(-dis[v],v));//优先队列是从大到小排,所以用负dis可实现从小到大排;而且dijkstra是直接入栈,不需要判断有没有在栈中
}
}
}
}
int main()
{
freopen("park.in","r",stdin);
freopen("park.out","w",stdout);
n=getint(),k=getint(),t=getint();
for(int i=1;i<=k;++i)
{
x=getint(),y=getint(),z=getint();
addedge(x,y,z);
}
dijkstra();
cout<<dis[n]<<'\n';
return 0;
}
本题结。