首页 > 搜索 > BFS搜索 > HDU 3191-How Many Paths Are There-动态规划-[解题报告]HOJ
2014
03-06

HDU 3191-How Many Paths Are There-动态规划-[解题报告]HOJ

How Many Paths Are There

问题描述 :

  oooccc1 is a Software Engineer who has to ride to the work place every Monday through Friday. For a long period, he went to office with the shortest path because he loves to sleep late…Time goes by, he find that he should have some changes as you could see, always riding with the same path is boring.
  One day, oooccc1 got an idea! Why could I take another path? Tired at all the tasks he got, he got no time to carry it out. As a best friend of his, you’re going to help him!
  Since oooccc1 is now getting up earlier, he is glad to take those paths, which are a little longer than the shortest one. To be precisely, you are going to find all the second shortest paths.
  You would be given a directed graph G, together with the start point S which stands for oooccc’1 his house and target point E presents his office. And there is no cycle in the graph. Your task is to tell him how long are these paths and how many there are.

输入:

There are some cases. Proceed till the end of file.
The first line of each case is three integers N, M, S, E (3 <= N <= 50, 0 <= S , E <N)
N stands for the nodes in that graph, M stands for the number of edges, S stands for the start point, and E stands for the end point.
Then M lines follows to describe the edges: x y w. x stands for the start point, and y stands for another point, w stands for the length between x and y.
All the nodes are marked from 0 to N-1.

输出:

There are some cases. Proceed till the end of file.
The first line of each case is three integers N, M, S, E (3 <= N <= 50, 0 <= S , E <N)
N stands for the nodes in that graph, M stands for the number of edges, S stands for the start point, and E stands for the end point.
Then M lines follows to describe the edges: x y w. x stands for the start point, and y stands for another point, w stands for the length between x and y.
All the nodes are marked from 0 to N-1.

样例输入:

3 3 0 2
0 2 5
0 1 4
1 2 2

样例输出:

6 1

/*
	对于这个题目我又该做何解释,Dijsk是过了的,可是优先队列 + BFS 就是Wrong,想不明白,xwc也改不出来
	渐渐的觉得我就是一个悲剧,为何总是会出现那么离奇的事情呢?开始对自己无语了,一下几乎完全是XWC的代码,
	因为我实在在自己写的找不出错误。何也??
求最短路和比最短路长一的路的总条数.

解法一、A*求第K短路,把前面K条路都求出来,象pku 2449 ,但是据说这个题的最后答案超过10^8,把路全部找出来肯定会爆priority_queue

解法二、

dp[i][1]表示到达点i最短的路有多少条,dp[i][2]表示次短的条数 

dist[i][1]表示到达点i最短路的长度,dist[i][2].........................

初始化为dist[st][1]=0 其他为max_int dp[st][1]=1 其他为0

用v去松驰u时有四种情况 (设当前dist[v][cas])

情况1:dist[v][cas]+w(v,u)<dist[u][1],找到一个更短的距离,则把原来最短的距离作为次短的距离,同时更新最短的.即

dist[u][2]=dist[u][1] 

dist[u][1]=dist[v][cas]+w(v,u);  

dp[u][2]=dp[u][1] 

dp[u][1]=dp[v][cas],

把Node(dist[u][1],u,1)和Node(dist[u][2],u,2)放入队列

情况2:dist[v][cas]+w(v,u)==dist[u][1],找到一条新的相同距离的最短路,则dp[u][1]+=dp[v][cas],其他不用更新,也不入队

情况3:dist[v][cas]+w(v,u)<dist[u][2],不可以更新最短距离,但可以更新次短的,则更新dist[u][2]和dp[u][2] 

dist[u][2]=dist[v][cas]+w(v,u); 

dp[u][2]=dp[v][cas];

把Node(dist[u][2],u,2)放入队列

情况4:dist[v][cas]+w(v,u)==dist[u][2] 找到一条新的相同距离的次短路,则dp[u][2]+=dp[v][cas],其他不更新。

*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int INF = 0x7f7f7f7f;
const int N = 55;
int cost[N][N];
bool hash[N][2];
int dis[N][2];
int dp[N][2];
void Dijsktra(int n, int s, int e)
{
	memset(hash, false, sizeof(hash));
	memset(dis, 0x7f, sizeof(dis));
	memset(dp, 0, sizeof(dp));
	dis[s][0] = 0;
	dp[s][0] = 1;
	int j;http://202.120.80.191 在for里面定义2次就是CE
	for(int i = 0; i < 2 * n; i++)
	{
		int min = INF;
		int x;
		int flag;
		for(j = 0; j < n; j++)
		{
			if(!hash[j][0] && dis[j][0] < min)
			{
				min = dis[j][0];
				x = j;
				flag = 0;
			}
			else if(!hash[j][1] && dis[j][1] < min)
			{
				min = dis[j][1];
				x = j;
				flag = 1;
			}
			
		}
		if(min == INF)
			break;
		hash[x][flag] = true;
		for(j = 0; j < n ; j++)
		{
			if(min + cost[x][j] < dis[j][0])
			{
				dis[j][1] = dis[j][0];
				dis[j][0] = min + cost[x][j];
				dp[j][1] = dp[j][0];
				dp[j][0] = dp[x][flag];
			}
			else if(min + cost[x][j] == dis[j][0])
			{
				dp[j][0] += dp[x][flag];
			}
			else if(min + cost[x][j] < dis[j][1])
			{
				dis[j][1] = min + cost[x][j];
				dp[j][1] = dp[x][flag];
			}
			else if(min + cost[x][j] == dis[j][1])
			{
				dp[j][1] += dp[x][flag];
			}
		}

	}


}
int main()
{
	int n, m, s, e;
	while(scanf("%d %d %d %d", &n, &m, &s, &e) != EOF )
	{
		int a, b, c;
		memset(cost, 0x7f, sizeof(cost));
		for(int i = 1; i <= m; i++)
		{
			scanf("%d %d %d", &a, &b, &c);
			cost[a][b] = c;
		}
		Dijsktra(n, s, e);
		printf("%d %d/n", dis[e][1], dp[e][1]);//printf("%d %d /n", dis[e][1], dp[e][1]);居然会写出这个的代码,在一个oj叫就是Wrong
							// 可是在hdu就是PE,我的god
	}
	return 0;//http://202.120.80.191  这里不加就是CE
}
/*
	为何这个就是错的???????????????????????????????? 
*/
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

struct node
{
	int num;
	int dis;
	int flag;
	friend bool operator < (node a, node b)
	{
		return a.dis > b.dis;
	}
};
const int N = 55;
const int INF = 0x7f7f7f7f;
int dis[N][2];
int dp[N][2];
int cost[N][N];
bool hash[N][2];
/*
void Init(int n)
{
	for(int i = 0; i <= n; i++)
	{
		hash[i][0] = false;
		hash[i][1] = false;
		dis[i][0] = INF;
		dis[i][1] = INF;
		dp[i][0] = 0;
		dp[i][1] = 0;
		for(int j = 0; j <= n; j++)
		{
			cost[i][j] = INF;
		}
	}
}
*/
void BFS(int n, int s, int e)
{
	priority_queue<node> Q;
	node P, M;
	memset(hash, false, sizeof(hash));
	memset(dp, 0, sizeof(dp));
	memset(dis, 0x7f, sizeof(dis));
	/*
	for(int i = 0; i < n; i++)
	{
		dis[i][0] = cost[s][i];
		if(i != s && dis[i][0] != INF)
		{
			P.num = i;
			P.dis = dis[i][0];
			P.flag = 0;
			dp[i][0] = 1;
			Q.push(P);
		}
	}
	*/
	P.num = s;
	P.dis = 0;
	P.flag = 0;
	dis[s][0] = 0;
	dp[s][0] = 1;
	Q.push(P);
	while(!Q.empty())
	{
		M = Q.top();
		Q.pop();
		if(M.dis == INF)
		break;
		hash[M.num][M.flag] = true;
		for(int i = 0; i < n; i++)
		{
			if(M.dis + cost[M.num][i] < dis[i][0] )
			{

				
				dis[i][1] = dis[i][0];
				P.dis = dis[i][1];
				P.flag = 1;
				P.num = i;
				Q.push(P);	
				dp[i][1] = dp[i][0];

				dis[i][0] = M.dis + cost[M.num][i];
				P.dis = dis[i][0];
				P.num = i;
				P.flag = 0;
				Q.push(P);
				dp[i][0] = dp[M.num][M.flag];
			}
			else if(M.dis + cost[M.num][i] == dis[i][0] )
			{
				dp[i][0] += dp[M.num][M.flag];
			}
			else if(dis[i][1] >  M.dis + cost[M.num][i] )
			{
				dis[i][1] = M.dis + cost[M.num][i];
				dp[i][1] = dp[M.num][M.flag];
				P.dis = dis[i][1];
				P.num = i;
				P.flag = 1;
				Q.push(P);
				
			}
			else if(dis[i][1] ==  M.dis + cost[M.num][i])
			{
				dp[i][1] += dp[M.num][M.flag];
				
			}
		}

	}
}

int main()
{
	int n, m, s, e;
	while(scanf("%d %d %d %d", &n, &m, &s, &e) != EOF)
	{
		int x, y, d;
		for(int i = 0; i <= n; i++)
		for(int j = 0; j <= n; j++)
		cost[i][j] = INF;
		for(int i = 1; i <= m; i++)
		{
			scanf("%d %d %d", &x, &y, &d);
			cost[x][y] = d;
			
		}
		BFS(n, s, e);
		printf("%d %d/n", dis[e][1], dp[e][1]);
	}
}

参考:http://blog.csdn.net/huixisheng/article/details/5728415


  1. bottes vernies blanches

    I appreciate the efforts you men and women place in to share blogs on such sort of matters, it was certainly useful. Keep Posting!

  2. 学算法中的数据结构学到一定程度会乐此不疲的,比如其中的2-3树,类似的红黑树,我甚至可以自己写个逻辑文件系统结构来。

  3. 其实国内大部分公司对算法都不够重视。特别是中小型公司老板根本都不懂技术,也不懂什么是算法,从而也不要求程序员懂什么算法,做程序从来不考虑性能问题,只要页面能显示出来就是好程序,这是国内的现状,很无奈。