C–最短路
Time Limit: 7000MS
Memory Limit: 65536KB
Problem Description
给出一个带权无向图,包含n个点,m条边。求出s,e的最短路。保证最短路存在。
Input
多组输入。 对于每组数据。 第一行输入n,m(1<= n && n<=5*10^5,1 <= m && m <= 2*10^6)。
接下来m行,每行三个整数,u,v,w,表示u,v之间有一条权值为w(w >= 0)的边。
最后输入s,e。
Output
对于每组数据输出一个整数代表答案。
Example Input
3 1 1 2 3 1 2
Example Output
3
Hint
Author
zmx
#include <bits/stdc++.h>
using namespace std;
int dis[500004], i, k, n, m, check, u[4000004], v[4000004], w[4000004];
void Bellman();
int main()
{
int s, e, x, y, z, t;
while(scanf("%d %d", &n, &m) != EOF)
{
t = 1;
for(i = 1; i <= m; i++)
{
scanf("%d %d %d", &x, &y, &z);
u[t] = x, v[t] = y, w[t] = z;
t++;
u[t] = y, v[t] = x, w[t] = z;
t++;
}
scanf("%d %d", &s, &e);
m = m * 2;
for(i = 1; i <= n; i++)
dis[i] = INT_MAX;
dis[s] = 0;
Bellman();
printf("%d\n", dis[e]);
}
return 0;
}
void Bellman() //Bellman-Ford 算法
{
for(k = 1; k < n; k++)
{
check = 0;
for(i = 1; i <= m; i++)
{
if(dis[u[i]] != INT_MAX && dis[v[i]] > dis[u[i]] + w[i]) //如果不判断dis是否为最大值,可能会溢出
{
dis[v[i]] = dis[u[i]] + w[i];
check = 1;
}
}
if(check == 0)
break;
}
return ;
}
队列优化后
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int u[4000005], v[4000005], w[4000005];
int first[500005], next[4000005];
int dis[500005], book[500005];
int main()
{
int x, y, z, n, m, s, e, t, i, k;
while(scanf("%d %d", &n, &m) != EOF)
{
t = 1;
queue<int>q;
for(i = 1; i <= n; i++)
{
dis[i] = inf;
first[i] = -1;
book[i] = 0;
}
for(i = 1; i <= m; i++)
{
scanf("%d %d %d", &x, &y, &z);
u[t] = x, v[t] = y, w[t] = z;
next[t] = first[u[t]];
first[u[t]] = t;
t++;
u[t] = y, v[t] = x, w[t] = z;
next[t] = first[u[t]];
first[u[t]] = t;
t++;
}
m = m * 2;
scanf("%d %d", &s, &e);
dis[s] = 0;
q.push(s);
book[s] = 1;
while(q.size() > 0)
{
k = first[q.front()];
book[q.front()] = 0;
q.pop();
while(k != -1)
{
if(dis[v[k]] > dis[u[k]] + w[k])
{
dis[v[k]] = dis[u[k]] + w[k];
if(book[v[k]] == 0)
{
q.push(v[k]);
book[v[k]] = 1;
}
}
k = next[k];
}
}
printf("%d\n", dis[e]);
}
return 0;
}