`
人生难得糊涂
  • 浏览: 117384 次
社区版块
存档分类
最新评论

POJ1125-Dijkstra算法

 
阅读更多

题意:

给出若干个联系人,及每个联系人通知其他联系人所需的时间,求从哪个联系人开始通知所用时间最短,并求出最短时间。

很明显是图论中求最短路径问题,可以用floyd 算法或者Dijkstra算法。我这里分别用两种方法实现。

方法一:Dijkstra算法。

只要遍历每个人,对每个人都以他为起点调用Dijkstra算法,求出最长时间(注意这道题一个联系人可以同时通知多个联系 人,所以求出他通知他人的最大时间,则是他通知所以人所用时间)。然后在每个人的“最长时间中”求出最短的那个。即答案。

#include "iostream"
using namespace std;
#define len 110
#define MAXINT 9999999
int map[len][len];
int length[len];//记录v到length[k]的最短路径
int flag[len];//标记某点是否得到最短路径(即处理完毕)
int dis(int v,int num)//此方法即Dijkstra算法
{
	int i;
	int j;
	for ( i=1;i<=num;i++)
	{
		length[i]=map[v][i];//初始化第一组数据
		flag[i]=0;
	}
	length[v]=0;
	flag[v]=1;
	for (i=1;i<num;i++)
	{
		int min=MAXINT;
		int minindex=-1;
		for (j=1;j<=num;j++)//找到本次搜索中距离最小的那个
		{
			if (flag[j]==0&&j!=v)
			if (length[j]<min)
			{
				min=length[j];
				minindex=j;
			}
		}
		if (minindex!=-1)
		{
			flag[minindex]=1;//将本次搜索中最小的那个加入以已处理集合(即已经找到最短路径)
			for (j=1;j<=num;j++)
			{
				if (flag[j]==0)//更新未处理的点
				{
					if (length[j]>length[minindex]+map[minindex][j])
					{
						length[j]=length[minindex]+map[minindex][j];
					}
				}
		}
		}
		
	}
	int max=-1;
	for (i=1;i<=num;i++)
	{
		if (max<length[i])
		{
			max=length[i];
		}
	}
	return max;//返回最大的一条边
}
int main()
{
	int num;
	int i,j;
	while(true)
	{
		scanf("%d",&num);//num表示有几个人
		if (num==0)
		{
			break;
		}
		
		for (i=1;i<=num;i++)
		{
			int n;
			scanf("%d",&n);
			for (j=1;j<=num;j++)
			{
				map[i][j]=MAXINT;//这里不能用memset方法,memset方法只能初始化为0 ,1,-1
			}
			for (j=1;j<=n;j++)
			{
				int  t;
				scanf("%d",&t);
				scanf("%d",&map[i][t]);
			}
		}

		int min=MAXINT;//记录最短的时间
		int mini=1;//记录从哪个联系人开始
		for (i=1;i<=num;i++)//对每个联系人遍历
		{
			if (min>dis(i,num))
			{
				min=dis(i,num);
				mini=i;
			}
		}
		if (min>100)
		{
			printf("disjoint\n");
		}
		else
		{
			printf("%d %d\n",mini,min);
		}
		
	}
	return 0;
}

 方法二:floyd算法

floyd算法是用来求图中的两点到两点之间的最短距离.。

其状态转移方程为: dp[i][j]=min(dp[i][k]+dp[k][j],dp[i][j]);dp[i][j]为点i到点j的最短路径,k为中间点.

于是我们可以很简单写出floyd的代码

 

for (i=1;i<=num;i++)
{
	for (j=1;j<=num;j++)
	{
		for (int k=1;k<=num;k++)
		{
			if (dp[i][j]>dp[i][k]+dp[k][j])
			{
				dp[i][j]=dp[i][k]+dp[k][j];
			}
					
		}
	}
}
 那么上述代码有没有问题呢?

 

有修改
把检查所有节点X放在最内层,那么结果将是不正确的,为什么呢?因为这样便过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。


 

图中红色的数字代表边的权重。如果我们在最内层检查所有节点X,那么对于 A->B,我们只能发现一条路径,就是A->B,路径距离为9。而这显然是不正确的,真实的最短路径是 A->D->C->B,路径距离为6。造成错误的原因就是我们把检查所有节点X放在最内层,造成过早的把A到B的最短路径确定下来了,当确定A->B的最短路径时Dis(AC)尚未被计算。所以,我们需要改写循环顺序,如下:

for (int k=1;k<=num;k++)
{
	for (i=1;i<=num;i++)
	{
		for (j=1;j<=num;j++)
		{			
			if (dp[i][j]>dp[i][k]+dp[k][j])
			{
				dp[i][j]=dp[i][k]+dp[k][j];
			}			
		}
	}
}

 

 

那么完整的代码如下:

#include "iostream"
using namespace std;
#define len 110
#define MAXINT 9999999
int map[len][len];
int dp[len][len];
int main()
{
	int num;
	int i,j;
	while(true)
	{
		scanf("%d",&num);//num表示有几个人
		if (num==0)
		{
			break;
		}
		
		for (i=1;i<=num;i++)
		{
			int n;
			scanf("%d",&n);
			for (j=1;j<=num;j++)
			{
				map[i][j]=MAXINT;//这里不能用memset方法,memset方法只能初始化为0 ,1,-1
			}
			for (j=1;j<=n;j++)
			{
				int  t;
				scanf("%d",&t);
				scanf("%d",&map[i][t]);
			}
		}
		for (i=1;i<=num;i++)
		{
			for (j=1;j<=num;j++)
			{
				dp[i][j]=map[i][j];
			}
		}
		for (int k=1;k<=num;k++)
		{
			for (i=1;i<=num;i++)
			{
				for (j=1;j<=num;j++)
				{
					if (dp[i][j]>dp[i][k]+dp[k][j])
					{
						dp[i][j]=dp[i][k]+dp[k][j];
					}
					
				}
			}
		}
		
		int max[len];
		memset(max,-1,sizeof(max));
		int ans=MAXINT;
		int ansi;
		for (i=1;i<=num;i++)//找以i为起点,最大的路径
		{
			for (j=1;j<=num;j++)
			{
				if (i!=j)
					if (max[i]<dp[i][j])
					{
						max[i]=dp[i][j];
					}
			}
			if (ans>max[i])//再每个点的最大路径中找到最小的那个
			{
				ansi=i;
				ans=max[i];
			}
		}
		if (ans==MAXINT)//说明有孤立点
			printf("disjoint\n");	
		else
			printf("%d %d\n",ansi,ans);
		
	}
	return 0;
}

 

 

  • 大小: 2.5 KB
分享到:
评论

相关推荐

    北大POJ初级-基本算法

    6. **图论算法**:包括图的遍历(深度优先搜索和广度优先搜索)、最短路径问题(Dijkstra算法、Floyd-Warshall算法)、最小生成树问题(Prim和Kruskal算法)。 7. **字符串处理**:如KMP算法、Rabin-Karp算法、...

    北大POJ初级-图算法

    3. **Dijkstra算法**:这是解决单源最短路径问题的经典算法,适用于有向图或无向图,但边的权重必须非负。Dijkstra算法通过维护一个优先队列,逐步找到从源节点到其他所有节点的最短路径。 4. **Floyd-Warshall算法...

    北大POJ中级-基本算法

    // 示例:Dijkstra算法 void dijkstra(vector, int&gt;&gt; graph[], int src) { priority_queue, int&gt;, vector, int&gt;&gt;, greater, int&gt;&gt;&gt; pq; pq.push({0, src}); vector&lt;int&gt; dist(graph.size(), INT_MAX); dist...

    POJ1062-Expensive dowry【dijkstra】

    【标题】"POJ1062-Expensive dowry【dijkstra】"涉及的问题是图论中的一个重要算法——Dijkstra算法,这是一个用于求解单源最短路径问题的算法,通常在计算机科学和信息技术领域有广泛应用,如路由选择、网络优化等...

    POJ3411-Paid Roads【class】

    3. 图算法:可能涉及Dijkstra算法、Floyd-Warshall算法或者Bellman-Ford算法来寻找最小费用路径。 4. 编程竞赛策略:如何高效地编写代码以通过所有测试用例。 5. 代码调试与优化:通过解题报告理解如何调试代码并...

    POJ2516-Minimum Cost

    读者可以通过阅读代码了解算法的具体实现,比如可能使用了Dijkstra算法、Floyd-Warshall算法或者Bellman-Ford算法等。 2. "POJ2516-Minimum Cost.doc":这可能是一个Word文档,详细记录了解题思路、算法解释、代码...

    POJ1523 - SPF 测试数据

    Dijkstra算法适用于无负权边的图,它以贪心策略为基础,每次选择当前未访问节点中距离源点最近的一个进行扩展。而Bellman-Ford算法则能处理含有负权边的情况,通过松弛操作逐步更新最短路径信息,可以检测出负权环...

    POJ3259--Wormholes(bellman).rar_wormhole code _wormholes

    它能够处理带有负权边的图,这是Dijkstra算法无法处理的情况。算法的基本思想是松弛操作,即逐步更新每条边上的路径长度,直到达到稳定状态,即不存在更短的路径。这个过程最多进行V-1次(V为图中节点的数量),因为...

    POJ 分类题目

    - **定义**:包括 Dijkstra 算法、Bellman-Ford 算法、Floyd 算法以及堆优化的 Dijkstra 算法。 - **示例题目**: - poj1860 - poj3259 - poj1062 - poj2253 - poj1125 - poj2240 - **应用场景**:适用于寻找...

    POJ3295-Tautology

    1. "POJ3295-Tautology.cpp":这是使用C++语言编写的代码,可能包含了作者解决此问题的算法实现。C++是常用的编程语言,尤其适合处理算法竞赛中的高效计算。 2. "POJ3295-Tautology【STL-stack】.cpp":这个文件名...

    POJ1724-ROADS

    2. **算法设计**:描述所采用的算法思想,可能是Dijkstra算法寻找最短路径,或者是Floyd-Warshall算法处理所有点对间的最短距离,或者是Ford-Fulkerson方法解决网络流问题。 3. **时间复杂度与空间复杂度分析**:...

    POJ2531-Network Saboteur

    5. **最短路径算法**:Dijkstra's Algorithm或Floyd-Warshall Algorithm可能会被用于找到关键节点,这些节点的破坏会导致网络通信的最大影响。 6. **数据结构**:C++代码中可能使用了数组、链表、队列或堆栈等数据...

    ACM题目分类.txt

    - **描述**:最短路径算法包括Dijkstra算法、Bellman-Ford算法、Floyd算法等。 - **应用场景**:求解两点之间的最短路径。 - **相关题目**: - POJ 1860 - POJ 3259 - POJ 1062 - POJ 2253 - POJ 1125 - POJ ...

    POJ2632-Crashing Robots

    Dijkstra算法适用于无负权边的图,而Bellman-Ford则能处理负权边的情况,但本题通常假设不存在负权重的碰撞。 3. **动态规划**:动态规划思想在此问题中体现为,将状态定义为“在前n次碰撞后,所有机器人的状态”,...

    POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类

    - **解释**:最短路径算法包括Dijkstra算法、Bellman-Ford算法、Floyd算法以及堆优化的Dijkstra算法等。 ##### (3) 最小生成树算法 - **例题**:poj1789, poj2485, poj1258, poj3026 - **解释**:最小生成树算法...

    北大POJ初级-动态规划

    3. **状态转移方程**:这是动态规划的关键,定义了如何从一个状态转移到另一个状态,例如Dijkstra算法中的“松弛操作”。 4. **初始条件**:设定问题的起始状态,通常是边界条件或者基本情况。 5. **解决方案**:...

    ACM-POJ 算法训练指南

    1. **最短路径**:Dijkstra算法、Bellman-Ford算法、Floyd算法等,用于寻找两点间最短路径(poj1860, poj3259, poj1062, poj2253, poj1125, poj2240)。 2. **最小生成树**:Prim算法和Kruskal算法,用于构建图的...

    acm新手刷题攻略之poj

    - 包括Dijkstra算法、Bellman-Ford算法以及Floyd算法等,用于求解图中两个节点间的最短路径。 2. **最小生成树** - 推荐题目:[poj1789](https://vjudge.net/problem/POJ-1789)、[poj2485]...

    算法训练方案详解

    - **定义**: 包括Dijkstra算法、Bellman-Ford算法和Floyd算法。 - **应用场景**: Dijkstra适用于非负权图中的单源最短路径问题;Bellman-Ford可以处理负权边但不能有负权环;Floyd用于解决任意两点之间的最短路径...

    POJ中级图算法所有题目【解题报告+AC代码】

    1. **最短路径问题**:包括Dijkstra算法和Floyd-Warshall算法。Dijkstra算法用于找到单源最短路径,适用于边权重非负的情况;而Floyd-Warshall算法可以找出所有对之间的最短路径,无论边权重是正还是负。 2. **最小...

Global site tag (gtag.js) - Google Analytics