Til the Cows Come Home 最短路Dijkstra+bellman(普通+优化)
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(普通+优化)的更多相关文章
- 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 ...
- 【POJ - 2387】Til the Cows Come Home(最短路径 Dijkstra算法)
Til the Cows Come Home 大奶牛很热爱加班,他和朋友在凌晨一点吃完海底捞后又一个人回公司加班,为了多加班他希望可以找最短的距离回到公司.深圳市里有N个(2 <= N < ...
- Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 32824 Accepted: 11098 Description Bes ...
- 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 ...
- Til the Cows Come Home(最短路模板题)
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu Description Bessie is ...
- 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 ...
- POJ 2387 Til the Cows Come Home --最短路模板题
Dijkstra模板题,也可以用Floyd算法. 关于Dijkstra算法有两种写法,只有一点细节不同,思想是一样的. 写法1: #include <iostream> #include ...
- POJ 2387 Til the Cows Come Home(最短路模板)
题目链接:http://poj.org/problem?id=2387 题意:有n个城市点,m条边,求n到1的最短路径.n<=1000; m<=2000 就是一个标准的最短路模板. #in ...
- POJ 3268 Silver Cow Party 最短路—dijkstra算法的优化。
POJ 3268 Silver Cow Party Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbe ...
随机推荐
- python解析字体反爬
爬取一些网站的信息时,偶尔会碰到这样一种情况:网页浏览显示是正常的,用python爬取下来是乱码,F12用开发者模式查看网页源代码也是乱码.这种一般是网站设置了字体反爬 一.58同城 用谷歌浏览器打开 ...
- JavaWeb_(SSH论坛)_五、帖子模块
基于SSH框架的小型论坛项目 一.项目入门 传送门 二.框架整合 传送门 三.用户模块 传送门 四.页面显示 传送门 五.帖子模块 传送门 六.点赞模块 传送门 七.辅助模块 传送门 回复帖子 分析回 ...
- Ajax+PHP实现的进度条--实例
之前重点学习PHP,所以javascript.Ajax都比较弱一点.现在也开始补课了,今天实现了一个进度条的例子,感觉Ajax实现动态页面真的很厉害,并没有想象中的那么难理解. 进度条作为反应实时传输 ...
- C#操作WMI文章汇总
http://blog.csdn.net/linux7985/article/details/5698932 http://www.cnblogs.com/ocean2000/archive/2008 ...
- SQL 表 数据备份
insert into SMTTemporarySave select * from [MSV0CIMDB].[PICS_20170706].dbo.SMTTemporarySave
- legend3---lavarel常用artisan命令操作
legend3---lavarel常用artisan命令操作 一.总结 一句话总结: 帮助:php artisan可以调出帮助命令 1.npm安装后盾js? npm install hdjs node ...
- vmx转换ofv模板,导入esxi
使用VMware Workstation安装目录下\OVFTool文件的ovftool.exe工具: 转换示例: 首先进入OVFTool根目录.然后执行 ovftool.exe "D:\ce ...
- linux 接收udp流花屏的问题
最近服务部署到一个Linux上面,接收udp的广播流花屏,问运维说带宽正常,就琢磨了一下应该的丢包了,程序本身申请的socket缓存还是蛮大的,就看看系统的缓存, 用命令cat /proc/sys/n ...
- 何为受控组件(controlled component)
在 HTML 中,类似 , 和 这样的表单元素会维护自身的状态,并基于用户的输入来更新:当用户提交表单时,前面提到的元素的值将随表单一起被发送.但在 React 中会有些不同,包含表单元素的组件将会在 ...
- FusionCharts的属性
FusionCharts 的 XML标签属性有一下四种数据类型 * Boolean - 布尔类型,只能为1或者0.例如:<graph showNames='1′ > * Number - ...