• POJ 1847 Tram【最短路入门Dijkstra算法模板题目一】


    原题链接:http://poj.org/problem?id=1847

    我的链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=19651#problem/D

    最短路模板题。

    Tram
    Time Limit: 1000MS   Memory Limit: 30000K
    Total Submissions: 7960   Accepted: 2861

    Description

    Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to the one of the rails going out of the intersection. When the tram enters the intersection it can leave only in the direction the switch is pointing. If the driver wants to go some other way, he/she has to manually change the switch. 

    When a driver has do drive from intersection A to the intersection B he/she tries to choose the route that will minimize the number of times he/she will have to change the switches manually. 

    Write a program that will calculate the minimal number of switch changes necessary to travel from intersection A to intersection B. 

    Input

    The first line of the input contains integers N, A and B, separated by a single blank character, 2 <= N <= 100, 1 <= A, B <= N, N is the number of intersections in the network, and intersections are numbered from 1 to N. 

    Each of the following N lines contain a sequence of integers separated by a single blank character. First number in the i-th line, Ki (0 <= Ki <= N-1), represents the number of rails going out of the i-th intersection. Next Ki numbers represents the intersections directly connected to the i-th intersection.Switch in the i-th intersection is initially pointing in the direction of the first intersection listed. 

    Output

    The first and only line of the output should contain the target minimal number. If there is no route from A to B the line should contain the integer "-1".

    Sample Input

    3 2 1
    2 2 3
    2 3 1
    2 1 2
    

    Sample Output

    0

    Source


    题意:给出N个站点,每个站点都有铁路通向其它的多个站点。

          如果当前要走的铁路是现在开关指向的铁路,则直接走即可,否则要手动扳动开关。

         

          第一行给出了站点的总数、起点和终点的标号。

          剩下的N行:表示1~N 个站点的铁路连接情况。

                       每行的第一个数表示该站点的铁路数,第二个数,表示当前默认通往

                       的站点。

    思路:最短路问题 Dijonkstra 算法

          把需要扳动的次数看成是路径长度建图即可。

    最朴素的Dijkstra 算法分析 PS:来自 《算法竞赛入门经典》 刘汝佳 P202
    
    伪代码:
    清除所有点的标号
    设d[0]=0, 其它d[i] = INF
    循环n次
    {
    	在所有未标号节点中,选出d值 最小的节点 x
    	标记节点 x
    	对于从x 出发的说有边(x,y),更新 d[y] = min(d[y], d[x]+w[x][y])
    } 
    
    对应代码
    假设起点节点为0,d[i] 表示起点到i的长度。
    v[i]=0 表示未标号 v[i]=1表示已标号 
    w[x][y]==INF 表示边(x,y) 不存在。
    
    memset(v,0,sizeof(v));
    for(int i = 0; i < n; i++) d[i] = (i==0 ? 0 : INF);
    for(int i = 0; i < n; i++)
    {
    	int x ,m = INF;
    	for(int y=0; y<n; y++) if(!v[y] && d[y]<=m) m=d[x=y];
    	v[x] = 1;
    	for(int y=0; y<n; y++) d[y] <?= d[x]+w[x][y];
    } 
    

    //Accepted	212 KB	0 ms	C++	1096 B	2013-02-27 19:42:55
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 110;
    const int INF = 100000000;
    
    int w[maxn][maxn]; //w[i][j]表示是否连通 0默认 1需手动调节 INF不连通 
    bool vis[maxn]; //标记是否使用 
    int dist[maxn]; //dist[i]表示从起点到点i的距离 
    
    int n,start,end; //点的个数,起点,终点 
    
    void Dijkstra()
    {
    	memset(vis,false,sizeof(vis)); //清除所有的点 
    	for(int i=1;i<=n;i++)
    		dist[i] = w[start][i];
    		
    	dist[start] = 0;
    	vis[start] = true; //标记起点 
    	
     	for(int i=1; i<=n; i++) //循环n 次 
     	{
     		int x, m = INF;
    		for(int y = 1; y <= n; y++) //在所有未标号的节点中,选出dist值的最小点x 
    			if(!vis[y] && dist[y] <= m)
    				m = dist[x=y];
    		vis[x] = true;//给节点 x 标记
    	 
    	 	for(int y = 1; y <= n; y++)//更新  松弛操作 
    		dist[y] = min(dist[y],dist[x]+w[x][y]);
    	
    	}
    	if(dist[end] == INF) printf("-1\n");
    	else printf("%d\n", dist[end]);
    }
    int main()
    {
    	while(scanf("%d%d%d", &n, &start, &end)!=EOF)
    	{ 
    		for(int i=1;i<=n;i++)
    		{
    			dist[i] = INF;
    			for(int j=1;j<=n;j++)
    				w[i][j] = INF;
    		}
    		
    		int path,y;
    		
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%d", &path);
    			for(int j=1;j<=path;j++)
    			{
    				scanf("%d",&y);
    				if(j==1) w[i][y] = 0;//默认 
    				else w[i][y] = 1; //需手动调节 
    			}
    		}
    		Dijkstra();
    	}
    	return 0;
    }



    PS:第一道Dijkstra题目有待优化中。。。。。下面的代码是直接暴力的。。。



    //暴力。。。 
    //Accepted	212 KB	0 ms	C++	1725 B	2013-02-27 19:29:00
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 110;
    const int INF = 10000000;
    
    int dist[maxn][maxn];
     
    int n,start, end;
    
    int main()
    {
    	scanf("%d%d%d",&n,&start,&end);
    	{
    		for(int i=1;i<=n;i++)
    		{ 
    			for(int j=1;j<=n;j++)
    				if(i==j) dist[i][j] = 0;
    				else dist[i][j] = INF;
    		}
    		
    		int path,y;
    		for(int i=1;i<=n;i++)
    		{
    			scanf("%d",&path);
    			for(int j=1;j<=path;j++)
    			{
    				scanf("%d",&y);
    				if(j==1) dist[i][y]=0;
    				else dist[i][y]=1;
    			}
    		}
    		for(int i=1;i<=n;i++)
      			for(int j=1;j<=n;j++)
         			for(int k=1;k<=n;k++)
            			dist[j][k] =min(dist[j][k],dist[j][i] + dist[i][k] );   
    	} 
    	if(dist[start][end]==INF) printf("-1\n");
    	else printf("%d\n",dist[start][end]);
    	return 0;
    }


  • 相关阅读:
    合理处理沉没成本
    推荐一个基于Ajax的查询API网站
    为blog添加天气预报功能
    我仅仅一个熟练的coder
    管理和IT的对话
    10个你未必知道的CSS技巧
    如何使用ajax开发web应用程序(二)
    5月20日,系分考试后感。
    说说大型高并发高负载网站的系统架构
    盗用sina的爱问投诉代码实现网页对话框。
  • 原文地址:https://www.cnblogs.com/freezhan/p/2950436.html
Copyright © 2020-2023  润新知