original link - http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=1211
题意:
给定M条边,N个点的带权无向图,求1到N的最短路
解析:
先讲一下一般做题时可以用到的优化:
1. 显然,当一个点被 v i s vis vis过(当作最近点后),下一次不会再 p u s h push push这个点了,但是不保证之前是否有压入这个点的不良状态。所以被 v i s vis vis过的点直接 c o n t i n u e continue continue可以保证每个点只跑一次。
2. 假设我们只求到一个点的最短路,那么显然,如果当前更新的答案劣于终点的答案,就不用压到队列里面去了。
3. 如果终点作为最近的点时,直接输出答案即可。
迪杰斯特拉模板:
#include
#include
#include
#include
#define N 100009
using namespace std;
int read(){ int ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
int head[N],now;
struct edge{
int to,nex,val;
}e[10*N];
void add(int a,int b,int v){
e[++now].to=b;e[now].nex=head[a];e[now].val=v;head[a]=now;
e[++now].to=a;e[now].nex=head[b];e[now].val=v;head[b]=now;
}
int n,m,a,b,v;
struct node{
int _id,dis;
node(int _id,int dis):_id(_id),dis(dis){}
bool operator < (const node &a) const{
return dis>a.dis;
}
};
priority_queue<node>Q;
int vis[N];
int dist[N];
int main(){
memset(head,-1,sizeof(head));now=0;
memset(dist,0x3f,sizeof(dist));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
a=read();b=read();v=read();add(a,b,v);
}
Q.push(node(1,0));
dist[1]=0;
while(!Q.empty()){
int j=Q.top()._id;Q.pop();
if(vis[j])continue;
vis[j]=1;
if(j==n){
printf("%d\n",dist[n]);
break;
}
for(int i=head[j];i!=-1;i=e[i].nex){
if(vis[e[i].to])continue;
if(dist[e[i].to]-e[i].val>dist[j] && dist[n]-e[i].val>dist[j]){
dist[e[i].to]=e[i].val+dist[j];
Q.push(node(e[i].to,dist[e[i].to]));
}
}
}
}
还有一种优化,用 p a i r pair pair代替 s t r u c t struct struct,因为 p a i r pair pair是自带的东西,比较大小什么的都比自己写的结构体优一点。
因为优先队列按照 f i r s t first first升序排序,所以压进优先队列里面的 p a i r pair pair以 f i r s t first first为距离, s e c o n d second second为点的id
#include
#include
#include
#include
#include
#include
#define N 100009
#define ll long long
#define pill pair
#define pb push_back
#define mk make_pair
using namespace std;
ll read(){ ll ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;}
vector<pill> v[N];
priority_queue<pill,vector<pill>,greater<pill> >Q;
int vis[N];
int dist[N];
int main(){
memset(dist,125,sizeof(dist));
int n=read(),m=read();
for(int i=1;i<=m;i++){
int a=read(),b=read(),c=read();
v[a].pb(mk(b,c));v[b].pb(mk(a,c));
}
Q.push(mk(0,1));dist[1]=0;
while(!Q.empty()){
int j=Q.top().second;Q.pop();
if(vis[j])continue;vis[j]=1;
for(int i=0;i<v[j].size();i++){
if(vis[v[j][i].first])continue;
if(dist[v[j][i].first]>dist[j]+v[j][i].second){
dist[v[j][i].first]=dist[j]+v[j][i].second;
Q.push(mk(dist[v[j][i].first],v[j][i].first));
}
}
}
printf("%d\n",dist[n]);
}
original link - http://acm.zjnu.edu.cn/CLanguage/showproblem?problem_id=1412)
#include
#include
#include
#include
#include
#include
#include
#define D long long
#define pill pair
#define mk make_pair
using namespace std;
vector<pill>V[10009];
priority_queue<pill,vector<pill>,greater<pill> >Q;
int vis[10009],dis[10009];
int n,m;
int main(){
while(cin>>m>>n){
while(!Q.empty())Q.pop();
for(int i=1;i<=n;i++)dis[i]=1e9,vis[i]=0,V[i].clear();
while(m--){
int a,b,v;scanf("%d%d%d",&a,&b,&v);
V[a].push_back(mk(b,v));
V[b].push_back(mk(a,v));
}
dis[1]=0;vis[1]=1;
Q.push(mk(0,1));
while(!Q.empty()){
pill e=Q.top();Q.pop();
int Id=e.second,val=e.first;
vis[Id]=1;
if(Id==n)break;
for(int i=0;i<V[Id].size();i++){
int a=V[Id][i].first,b=V[Id][i].second;
if(vis[a])continue;
if(dis[Id]<dis[a]-b){
dis[a]=dis[Id]+b;
Q.push(mk(dis[a],a));
}
}
}
printf("%d\n",dis[n]);
}
}