题解 P1807 【最长路_NOI导刊2010提高(07)】
题目链接
思路点播:
数据结构:用结构体e保存每一条边,d[i]表示从1到i的最长路,v[i]==true则表示i号节点在队列q中,v[i]==false则表示不在,b[i]==true则表示1可以到达i,b[i]==false则表示1不能到达i
算法过程:
1、读入数据,并储存每一条边
const int N=1510,M=50100;
struct node{
int next,to,len;
}e[M];int head[N],cnt;
void add_node_edge(int x,int y,int z){
e[++cnt]=(node){head[x],y,z};head[x]=cnt;
}
int main(){
n=read();m=read();
for(i=1;i<=m;i++){
x=read();y=read();z=read();
add_node_edge(x,y,z);
//若题目为无向图,则再加一句:
//add_node_edge(y,x,z)
}
}
其中,read()函数为读入优化(听说每500万个数据可省100ms)
#define g(c) isdigit(c)
#define gc getchar()
inline int read(){
char c=0;int x=0,f=0;
while (!g(c)) f|=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
//需要调用cctype库
2、套用spfa算法
queue<int> q;bool v[N],b[N];
inline void spfa_algorithm(){
memset(d,0,sizeof(d));
memset(v,1,sizeof(v));
memset(b,0,sizeof(b));
q.push(1);v[1]=false;b[1]=1;
//1号节点可以到达
while (q.size()){
int z=q.front();q.pop();v[z]=1;
for(int i=head[z];i;i=e[i].next){
register int u=e[i].to;
if (d[u]<d[z]+e[i].len){
d[u]=d[z]+e[i].len;b[u]=1;
//u号节点被扩展到说明它可以到达
if (v[u]){
q.push(u);v[u]=false;
}
}
}
}
}
3、根据b[n]和d[n]的值输出
if (b[n]==0) printf("-1");//n号节点无法到达,输出-1
else printf("%d",d[n]);//n号节点可以到达,输出最长路
评测记录:
状态/分数:Accepted,100分
语言/长度:C++,1.21KB
耗时/内存:57ms,1552KB
#include <bits/stdc++.h>
using namespace std;
const int N=1510,M=50100;
struct node{
int next,to,len;
}e[M];int head[N],cnt;
void add_node_edge(int x,int y,int z){
e[++cnt]=(node){head[x],y,z};head[x]=cnt;
}
int d[N],n,m,i,x,y,z;
#define g(c) isdigit(c)
#define gc getchar()
inline int read(){
char c=0;int x=0,f=0;
while (!g(c)) f|=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
queue<int> q;bool v[N],b[N];
inline void spfa_algorithm(){
memset(d,0,sizeof(d));
memset(v,1,sizeof(v));
memset(b,0,sizeof(b));
q.push(1);v[1]=false;b[1]=1;
while (q.size()){
int z=q.front();q.pop();v[z]=1;
for(int i=head[z];i;i=e[i].next){
register int u=e[i].to;
if (d[u]<d[z]+e[i].len){
d[u]=d[z]+e[i].len;b[u]=1;
if (v[u]){
q.push(u);v[u]=false;
}
}
}
}
}
int main(){
n=read();m=read();
for(i=1;i<=m;i++){
x=read();y=read();z=read();
add_node_edge(x,y,z);
}
spfa_algorithm();
if (b[n]==0) printf("-1");
else printf("%d",d[n]);
return 0;
}
最后,说一下万能头bits/stdc++.h
noi比赛文件中说:理论上可以用万能头,但实际中可能不支持使用万能头,若因为使用万能头而导致CE(编译错误),比赛概不负责,即选手负全责!!!
所以,比赛时建议不要使用万能头,平时可以稍微使用一下