Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化)

贝西在田里,想在农夫约翰叫醒她早上挤奶之前回到谷仓尽可能多地睡一觉。贝西需要她的美梦,所以她想尽快回来。

农场主约翰的田里有n(2<=n<=1000)个地标,唯一编号为1..n。地标1是谷仓;贝西整天站在其中的苹果树林是地标n。奶牛在田里行走时使用地标间不同长度的T(1<=t<=2000)双向牛道。贝西对自己的导航能力没有信心,所以一旦开始,她总是沿着一条从开始到结束的路线行进。

根据地标之间的轨迹,确定贝西返回谷仓必须走的最小距离。这样的路线一定存在。

解题思路

这个题是很典型的最短路问题,并且给了起点和终点,所以使用Dijkstra算法来解决单源最短路问题。

Dijkstra算法我这有两种形式,一种是普通的邻接矩阵法,复杂度是\(O(n^2)\),n是顶点的个数

然而使用邻接表和优先队列的形式,可以将复杂度优化到\(O(m*logn)\),m是边的个数,但是这种一般适用于稀疏图,对于稠密图,这种优化算法可能比原来没有优化的复杂度还要高。参考《算法竞赛入门经典(第二版)》360页

这个题也可以用Bellman算法来进行实现。

代码实现

//普通的临界矩阵算法 dijkstra算法
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int inf=0x3f3f3f3f;
const int maxn=1e3+7;
int mp[maxn][maxn];
int dis[maxn];
int vis[maxn];
int t, n; void dij()
{
for(int i=1; i<=n; i++)
{
dis[i]=mp[1][i];
}
vis[1]=1;
for(int i=1; i<n; i++)
{
int tmp=inf, k;
for(int j=1; j<=n; j++)
{
if(!vis[j] && dis[j]<tmp)
{
tmp=dis[j];
k=j;
}
}
vis[k]=1;
for(int j=1; j<=n; j++)
{
if(!vis[j] && dis[j] > dis[k]+mp[k][j])
dis[j]=dis[k] + mp[k][j];
}
}
} void init()
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(i!=j) mp[i][j]=inf;
else mp[i][j]=0;
}
}
fill(vis+1, vis+n+1, 0);
fill(dis+1, dis+n+1, inf);
}
int main()
{
while(scanf("%d%d", &t, &n)!=EOF)
{
int a, b, c;
init();
for(int i=1; i<=t; i++)
{
scanf("%d%d%d", &a, &b, &c);
if(c < mp[a][b])
{
mp[a][b]=c;
mp[b][a]=c;
}
}
dij();
printf("%d\n", dis[n]);
}
return 0;
}

优化的Dijkstra算法

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=1e3+7;
const int maxe=2e3+7;
const int inf=0x3f3f3f3f;
struct edge{
int to, cost;
};
struct headnode{
int d, u;
bool friend operator < (const headnode a, const headnode b)
{
return a.d > b.d; //使用大于号是因为在优先队列中默认是从大到小的,这里需要反过来,从小到大。
}
};
int dis[maxn];
int vis[maxn];
vector<edge> g[maxn];
priority_queue<headnode> que;
int t, n;
void init()
{
for(int i=1; i<=n; i++)
{
g[i].clear();
vis[i]=0;
dis[i]=inf;
}
while(!que.empty()) que.pop();
}
void dij(int s)
{
int u;
edge e;
dis[s]=0;
headnode tmp={0, s};
headnode next;
que.push(tmp);
while(!que.empty())
{
tmp=que.top();
que.pop();
u=tmp.u;
if(vis[u]==1) continue;
vis[u]=1;
for(int i=0; i<g[u].size(); i++)
{
e=g[u][i];
if(dis[e.to] > dis[u]+e.cost)
{
dis[e.to]=dis[u]+e.cost;
next.d=dis[e.to];
next.u=e.to;
que.push(next);
}
}
}
}
int main()
{
while(scanf("%d%d", &t, &n)!=EOF)
{
init();
int a, b, c;
edge e;
for(int i=1; i<=t; i++)
{
scanf("%d%d%d", &a, &b, &c);
e.to=b;
e.cost=c;
g[a].push_back(e);
e.to=a;
e.cost=c;
g[b].push_back(e);
}
dij(1);
printf("%d\n", dis[n]);
}
return 0;
}

Bellman算法

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int maxn=1e3+7;
const int maxe=4e3+7; //这里一定要注意,t是路的条数,但是存图时每条路需要存储两遍。
const int inf=0x3f3f3f3f; struct edge{
int a, b, c;
}e[maxe]; int dis[maxn];
int t, n, cnt; // bool bellman(int s)
{
for(int i=1 ;i<=n; i++)
dis[i]=inf;
dis[s]=0;
bool flag;
int x, y, z;
for(int i=1; i<n; i++)
{
flag=false;
for(int j=1; j<cnt; j++)//cnt-1是边的条数
{
x=e[j].a;
y=e[j].b;
z=e[j].c;
if(dis[y] >= dis[x] + z)
{
dis[y]=dis[x]+z;
flag=true;
}
}
if(!flag)
break;
if(flag && i==n)
return false;
}
return true;
} int main()
{
while(scanf("%d%d", &t, &n)!=EOF)
{
int a, b, c;
cnt=1;
for(int i=1; i<=t; i++)
{
scanf("%d%d%d", &a, &b, &c);
e[cnt].a=a; e[cnt].b=b; e[cnt++].c=c;
e[cnt].a=b; e[cnt].b=a; e[cnt++].c=c;
}
bellman(1);
printf("%d\n", dis[n]);
}
return 0;
}

优化的Bellman算法,也就是鼎鼎大名的SPFA。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn=1e3+7;
const int inf=0x3f3f3f3f;
struct edge
{
int to, cost;
edge(){}
edge(int a, int b)
{
to=a;
cost=b;
}
};
int dis[maxn];
bool inq[maxn];
int cnt[maxn];
vector<edge> g[maxn];
queue<int>que;
int t, n;
bool spfa(int s)
{
for(int i=1; i<=n; i++)
{
dis[i]=inf;
inq[i]=false;
cnt[maxn]=0;
}
while(!que.empty()) que.pop(); edge e;
dis[s]=0;
inq[s]=true;
que.push(s);
while(!que.empty())
{
int u=que.front();
que.pop();
inq[u]=false;
for(int i=0; i<g[u].size() ; i++)
{
e=g[u][i];
if(dis[e.to] > dis[u]+e.cost)
{
dis[e.to] = dis[u]+e.cost;
if(inq[e.to]==false)
{
inq[e.to]=true;
que.push(e.to);
cnt[e.to]++;
if(cnt[e.to]>=n) return false; //这里是记录松弛的次数,如果达到n次说明有负环
}
}
}
}
return true;
}
int main()
{
while(scanf("%d%d", &t, &n)!=EOF)
{
int a, b, c;
for(int i=1; i<=n; i++)
g[i].clear();
for(int i=1; i<=t; i++)
{
scanf("%d%d%d", &a, &b, &c);
g[a].push_back(edge(b, c));
g[b].push_back(edge(a, c));
}
spfa(1);
printf("%d\n", dis[n]);
}
return 0;
}

Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化)的更多相关文章

  1. POJ2387 Til the Cows Come Home (最短路 dijkstra)

    AC代码 POJ2387 Til the Cows Come Home Bessie is out in the field and wants to get back to the barn to ...

  2. 【POJ - 2387】Til the Cows Come Home(最短路径 Dijkstra算法)

    Til the Cows Come Home 大奶牛很热爱加班,他和朋友在凌晨一点吃完海底捞后又一个人回公司加班,为了多加班他希望可以找最短的距离回到公司.深圳市里有N个(2 <= N < ...

  3. Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32824   Accepted: 11098 Description Bes ...

  4. POJ 2387 Til the Cows Come Home(模板——Dijkstra算法)

    题目连接: http://poj.org/problem?id=2387 Description Bessie is out in the field and wants to get back to ...

  5. Til the Cows Come Home(最短路模板题)

    Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Description Bessie is ...

  6. POJ-2387 Til the Cows Come Home ( 最短路 )

    题目链接: http://poj.org/problem?id=2387 Description Bessie is out in the field and wants to get back to ...

  7. POJ 2387 Til the Cows Come Home --最短路模板题

    Dijkstra模板题,也可以用Floyd算法. 关于Dijkstra算法有两种写法,只有一点细节不同,思想是一样的. 写法1: #include <iostream> #include ...

  8. POJ 2387 Til the Cows Come Home(最短路模板)

    题目链接:http://poj.org/problem?id=2387 题意:有n个城市点,m条边,求n到1的最短路径.n<=1000; m<=2000 就是一个标准的最短路模板. #in ...

  9. POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。

    POJ 3268 Silver Cow Party Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbe ...

随机推荐

  1. 51 Nod 1069 Nim游戏

    分析: a1 xor a2 xor a3 ... xor an !=0 则为必胜态 a1 xor a2 xor a3 ... xor an ==0 则为必败态 也就是说只要计算异或值,如果非零则A赢, ...

  2. 【杂题】[CodeForces 1172D] Nauuo and Portals【构造】

    Description 有一个n*n的网格,你需要在上面设置一些传送门,传送门由两个配对的格子组成,从一个进入会立刻从另一个同一方向出来. 现在有n个人从第1列出发向右走,位于(i,1)的人要走到(r ...

  3. sh_01_列表基本使用

    sh_01_列表基本使用 name_list = ["zhangsan", "lisi", "wangwu"] # 1. 取值和取索引 # ...

  4. redis安装成功后get: command not found

    安装redis后客户端无法使用,即redis-cli执行后报找不到的错误. 这主要是安装redis的时候没有把客户端装上,在StackOverFlow上找到了一种只安装redis cli的方法. 安装 ...

  5. supsplk 服务器被植入木马 挖矿 cpu使用 700%

    最近emr集群跑任务的时候总出现 task failed ,优化sql,调提交任务参数都没解决,最后再我排查时候,发现一个从节点的cpu使用800% 经过一些列排查,发现是被注入木马了, #被人种下的 ...

  6. json转换时 java.lang.ClassNotFoundException: org.apache.commons.lang.exception.NestableRuntimeException

    java.lang.ClassNotFoundException: org.apache.commons.lang.exception.NestableRuntimeException 遇到这种问题是 ...

  7. scrollWidth、clientWidth、offsetWidth、width的区别

    scrollWidth:对象的实际内容的宽度,不包边线宽度,会随对象中内容超过可视区后而变大. clientWidth:对象内容的可视区的宽度,不包滚动条等边线,会随对象显示大小的变化而改变. off ...

  8. C++入门经典-关于extern变量

    1:extern用于解决使用非本源文件的全局变量. 例如:在sample1.cpp中 int a,b; /*外部变来那个定义*/ char c; void main() { cout<<a ...

  9. Wazuh 实操

    https://www.jianshu.com/p/40c911a5628e?from=timeline&isappinstalled=0

  10. PADS常用画板过程

    转载:PADS LAYOUT的一般流程 http://www.doc88.com/p-9129306856292.html https://wenku.baidu.com/view/cc4e0b338 ...