#include
#include
#include
#include
#include
#include
#define MAXN 150005
const int INF = 9999999;
using namespace std;
int N, M;
struct node{
int to, cost;
int next;
};
node e[150005];
//e数组读取边的信息
int d[30005], adj[30005];
//d数组表示到原点的最短距离,adj表示某一点最后出现的位置;
bool vis[30005];
//访问数组
void spfa()
{
for (int i = 0; i < 30005; i++) d[i] = INF;
d[1] = 0;
memset(vis, 0, sizeof(vis));
int sta[30005];
////栈模拟,等价于用stack
int top = 0;
vis[1] = 1;
sta[++top] = 1;
while (top){
int pos = sta[top--];
vis[pos] = 0;
for (int i = adj[pos]; i != -1; i = e[i].next){
int to = e[i].to;
int cost = e[i].cost;
if (d[to] > d[pos] + cost){
d[to] = d[pos] + cost;
if (vis[to] == 0){
sta[++top] = to;
vis[to] = 1;
}
}
}
}
return;
}
int a, b, c;
int main()
{
while (scanf("%d%d", &N, &M) != EOF){
memset(vis,0,sizeof(vis));
for (int i = 0; i < 30005; i ++) adj[i] = -1;
//默认adj[i] = -1 时再往上找无边
//多组数据必要的清空
for (int i = 0; i < M; i++){
scanf("%d%d%d", &a, &b, &c);
e[i].to = b;
e[i].cost = c;
e[i].next = adj[a];
//next记录下上一次从a出发在e[i]中的位置
adj[a] = i;
//记录下出发点a最后一次出现的位置
}
spfa();
printf("%d\n", d[N]);
}
}
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
#define MAXN 1000005
using namespace std;
int N, M;
struct node{
int to, cost;
};
vector e[30005];
int d[30005];
bool vis[30005];
int cmp(int a, int b){return a > b;}
void spfa()
{
for (int i = 0; i < 30005; i++) d[i] = INF;
d[0] = 0;
d[1] = 0;
memset(vis, 0, sizeof(vis));
queue q;
vis[1] = 1;
q.push(1);
while (!q.empty()){
int tmp = q.front();
q.pop();
vis[tmp] = 0;
for (int i = 0; i < e[tmp].size(); i++){
node cur = e[tmp][i];
if (d[cur.to] > d[tmp] + cur.cost){
d[cur.to] = d[tmp] + cur.cost;
if (vis[cur.to] == 0){
q.push(cur.to);
vis[cur.to] = 1;
}
}
}
}
return;
}
int a, b, c;
node input;
int main()
{
while (scanf("%d%d", &N, &M) != EOF){
memset(vis,0,sizeof(vis));
for (int i = 0; i < M; i++){
scanf("%d%d%d", &a, &b, &c);
input.to = b;
input.cost = c;
e[a].push_back(input);
//存放到vector中
}
spfa();
sort(d, d+N+1, cmp);
printf("%d\n", d[0]);
}
}
#include //定义输入/输出函数
#include //定义各种数据类型最值常量
#include //定义数学函数
#include //定义杂项函数及内存分配函数
#include //字符串处理
#include //算法
#include //队列
#include //栈
using namespace std;
int N, M;
int re[1005]; //源根
int finds(int x){ //找根函数
if (re[x] == x) return x;
else return re[x] = finds(re[x]);
}
struct node{
int from, to, cost;
};
node a[20005];
int vis[1005];
int cmp(node a, node b){return a.cost > b.cost;}
long long sum;
int flag;
int main()
{
while (scanf("%d%d", &N, &M) != EOF){
for (int i = 0; i < M; i++)
scanf("%d%d%d", &a[i].from, &a[i].to, &a[i].cost);
sort(a, a+M, cmp);
//读取输入
for (int i = 0; i <= N; i++) re[i] = i;
//根重置
memset(vis, 0, sizeof(vis));
//访问重置
sum = flag = 0;
for (int i = 0; i < M; i++){
if (finds(a[i].from) == finds(a[i].to)) continue;
//如果查找后两数根不相等,则进行以下程序
re[finds(a[i].from)] = finds(a[i].to);
//直接把一根连在另一根的生成树上
vis[a[i].from] = 1;
vis[a[i].to] = 1;
sum += a[i].cost;
}
for (int i = 1; i <= N; i++){
if (vis[i] == 0) flag = 1;
if (finds(i) != finds(1)) flag = 1;
}
if (flag == 1) printf("-1\n");
else printf("%lld\n", sum);
}
}
#include //定义输入/输出函数
#include //定义各种数据类型最值常量
#include //定义数学函数
#include //定义杂项函数及内存分配函数
#include //字符串处理
#include //算法
#include //队列
#include //栈
#include //动态数组
using namespace std;
int T, N, pos, mins;
int map[505][505];
bool vis[505];
int low[505];
int cmp(int a, int b) {return a > b;}
int main()
{
while (scanf("%d", &T) != EOF){
while (T--){
memset(map, 0, sizeof(map));
memset(low, 0, sizeof(low));
memset(vis, 0, sizeof(vis));
scanf("%d", &N);
printf("N = %d\n", N);
for (int i = 1; i <= N; i++)
for (int j = 1; j <= N; j++)
scanf("%d", &map[i][j]);
for (int i = 1; i <= N; i++)
low[i] = map[1][i];
low[1] = 0;
vis[1] = pos = 1;
for (int i = 1; i < N; i++){
mins = 65550;
for (int j = 1; j <= N; j++)
if (vis[j] == 0 && mins > low[j]){
mins = low[j];
pos = j;
}
//在d[N]中找到最小值的位置
vis[pos] = 1;
for (int j = 1; j <= N; j++){
if(low[j] > map[pos][j] && vis[j] == 0)
low[j] = map[pos][j];
}
//用最小值的位置更新Low数组
}
//for (int i = 0; i <= N; i++) printf(" %d", low[i]);
//printf("\n");
sort(low, low + N + 1, cmp);
for (int i = 0; i <= N; i++) printf(" %d", low[i]);
printf("\n");
printf("%d\n", low[0]);
}
}
}
给定图G(V, E)(其中V、E分别为图G的顶点集与边集),源点s,数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]为, Distant[s]为0;
以下操作循环执行至多n-1次,n为顶点数:
对于每一条边e(u, v),如果Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值;
若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;
为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。
可知,Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).
②算法流程:
第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。
第二,进行循环,循环下标为从1到n-1(n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。
第三,遍历途中所有的边(edge(u,v)),判断是否存在这样情况:d(v) > d (u) + w(u,v) 存在则赋值;
③算法图示:
#include //定义输入/输出函数
#include //定义各种数据类型最值常量
#include //定义数学函数
#include //定义杂项函数及内存分配函数
#include //字符串处理
#include //算法
#include //队列
#include //栈
const int INF = 0x3f3f3f3f;
using namespace std;
struct node{
int to, cost;
int next;
};
node e[2][1000005];
int N, P, Q;
int adj[2][1000005], d[1000005];
bool vis[1000005];
int a, b, c;
long long sum;
void spfa(int k)
{
memset(vis, 0, sizeof(vis));
memset(d, INF, sizeof(d));
stack s;
//开queue 也行,一样时间与内存
s.push(1);
d[1] = 0;
vis[1] = 1;
while (!s.empty()){
int pos = s.top();
s.pop();
vis[pos] = 0;
for (int i = adj[k][pos]; i!= -1; i = e[k][i].next){
int to = e[k][i].to;
int cost = e[k][i].cost;
if (d[to] > d[pos] + cost){
d[to] = d[pos] + cost;
if (vis[to] == 0){
s.push(to);
vis[to] = 1;
}
}
}
}
}
int main()
{
while (scanf("%d", &N) != EOF){
while (N--){
memset(adj, -1, sizeof(adj));
memset(e, 0, sizeof(e));
sum = 0;
scanf("%d%d", &P, &Q);
for (int i = 0; i < Q; i++){
scanf("%d%d%d", &a, &b, &c);
e[0][i].to = b;
e[0][i].cost = c;
e[0][i].next = adj[0][a];
adj[0][a] = i;
e[1][i].to = a;
e[1][i].cost = c;
e[1][i].next = adj[1][b];
adj[1][b] = i;
}
spfa(0);
for (int i = 1; i <= P; i++) sum += d[i];
//printf("\n");
spfa(1);
for (int i = 1; i <= P; i++) sum += d[i];
//printf("\n");
printf("%lld\n", sum);
}
}
}