【题目描述】
给定一张地图,包含T个城镇(1 <= T <= 2500)和M(1 <= M <= 6200)条直接连接两个城镇的道路,每条道路由起点S、终点E(1 <= S <= T,1 <= E <= T)以及花费C(1 <= C <= 1000)构成,求从起始城镇Start(1 <= Start <= T)到终点城镇End(1 <= End <= T)所能得到的最小总费用是多少。
【输入描述】
第一行输入四个整数T、M、Start、End;
接下来M行,每行输入三个整数S、E、C。
【输出描述】
输出一个整数,表示答案。
【输入样例】
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1
【输出样例】
7
Dijkstra+优先队列优化:
源代码: #include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; struct Node { int To,S; Node(int t1,int t2) //似乎是强制类型转换。 { To=t1; S=t2; } bool operator < (const Node &t) const //看来得背过了,重载运算符。 { if (S==t.S) return To<t.To; //明显要快一点。 else return S>t.S; } }; priority_queue <Node> Q; vector <Node> Edge[2501]; int m,n,Start,End,i[2501]; void Dijkstra() { i[Start]=0; Q.push(Node(Start,i[Start])); while (!Q.empty()) { Node t=Q.top(); Q.pop(); for (int a=0;a<Edge[t.To].size();a++) { Node T=Edge[t.To][a]; if (i[T.To]>t.S+T.S) { i[T.To]=t.S+T.S; Q.push(Node(T.To,i[T.To])); //其实这才是更新,i[]不过是记录。 } } } } int main() //Dijkstra+优先队列。 { memset(i,0x3f,sizeof(i)); scanf("%d%d%d%d",&n,&m,&Start,&End); for (int a=0;a<m;a++) { int t,t1,t2; scanf("%d%d%d",&t1,&t2,&t); Edge[t1].push_back(Node(t2,t)); Edge[t2].push_back(Node(t1,t)); } Dijkstra(); printf("%d",i[End]); return 0; }
SPFA+SLF优化:
源代码: #include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; struct Node1 { int S,To,Next; }Edge[12401]; struct Node2 { int X,Y,S; }Map[12401]; deque <int> Q; //双端队列。 int m,n,Num(0),Start,End,i[2501],Sum[2501],Head[2501]; bool In[2501]={0}; void Add(int t1,int t2,int t) { Edge[++Num].To=t2; Edge[Num].S=t; Edge[Num].Next=Head[t1]; Head[t1]=Num; } int main() //SPFA+SLF+随机化排序,妈的谁还能卡我! { memset(i,0x3f,sizeof(i)); scanf("%d%d%d%d",&n,&m,&Start,&End); for (int a=0;a<m;a++) scanf("%d%d%d",&Map[a].X,&Map[a].Y,&Map[a].S); random_shuffle(Map,Map+m); //随机化排序。 for (int a=0;a<m;a++) { Add(Map[a].X,Map[a].Y,Map[a].S); Add(Map[a].Y,Map[a].X,Map[a].S); } i[Start]=0; Q.push_back(Start); In[Start]=true; while (!Q.empty()) { int t=Q.front(); Q.pop_front(); In[t]=false; for (int a=Head[t];a;a=Edge[a].Next) { int T=Edge[a].To; if (i[T]>i[t]+Edge[a].S) { Sum[T]=Sum[t]+1; if (Sum[T]>n) //判负环。 return 0; i[T]=i[t]+Edge[a].S; if (!In[T]) { In[T]=true; if (!Q.empty()&&i[Q.front()]>i[T]) Q.push_front(T); else Q.push_back(T); } } } } printf("%d",i[End]); return 0; }