(intermediate) 最短路(第k短路) UVA 10740 - Not the Best

Problem A
Not the Best
Input: standard input
Output: standard output
Time Limit: 1 second

 

Abul is not the best student in his class; neither is he the best player in his team. Not that he is bad; he is really good, but unfortunately not the best.

 

Last semester our “not quite the best” Abul took a course on algorithms. In one of the assignments he was required to find the shortest path from a given vertex x to another vertex y in a weighted directed graph. As you have probably already guessed, he rarely managed to find the shortest path; instead he always ended up finding the kth (2 ? k ? 10) shortest path from x to y. If he was fortunate enough and the shortest k paths from x to y had the same length, he was given credit for his solution.

(intermediate) 最短路(第k短路) UVA 10740 - Not the Best - 恶魔仁 - 恶魔仁

For example, for the graph above, Abul was asked to find the shortest path from vertex 5 to vertex 2. The shortest 7 paths from vertex 5 to vertex 2 are listed below in non-decreasing order of length. For this graph Abul was able to find the 5th shortest path which could be either 5 ? 4 ? 3 ? 2 ? 5 ? 1 ? 2 or 5 ? 1 ? 2 ? 5 ? 4 ? 3 ? 2, each with length 15.

 

Path

Length

5 ? 1 ? 2

5

5 ? 4 ? 3 ? 2

6

5 ? 1 ? 2 ? 5 ? 1 ? 2

14

5 ? 4 ? 3 ? 2 ? 5 ? 1 ? 2

15

5 ? 1 ? 2 ? 5 ? 4 ? 3 ? 2

15

5 ? 4 ? 3 ? 2 ? 5 ? 4 ? 3 ? 2

16

5 ? 1 ? 2 ? 5 ? 1 ? 2 ? 5 ? 1 ? 2

23

Given a description of the graph, source vertex x, target vertex y, and the value of k, you need to find out the length of the path Abul computed. You may assume that there exists at least one path from x to y in the given graph.

  
Input

The input may contain multiple test cases.

 

The first line of each test case contains two integers n (2 ? n ? 100) and m (1 ? m ? 1000) giving respectively the number of vertices, and the number of edges in the graph. Each vertex in the graph is identified by a unique integer in [1, n]. The second line of the test case contains the values of x, y and k (1 ? x, y ? 100, x ? y, 2 ? k ? 10). Each of the next m lines contains three integers u, v and l (1 ? u, v ? 100, 0 ? l ? 10000) specifying a directed edge of length l from vertex u to vertex v.

 

The input terminates with two zeros for n and m.

 

Output

For each test case in the input output a line containing an integer giving the length of the kth shortest path in the graph. If the graph does not have at least k paths from x to y, output a –1 instead.

 

Sample Input                               Output for Sample Input

3 3

1 3 4

1 3 3

1 2 4

2 3 5

5 6

5 2 5

1 2 2

2 5 4

3 2 3

4 3 1

5 1 3

5 4 2

2 2

1 2 3

1 2 5

2 2 2

0 0

-1

15

9

 


Problem setter: Rezaul Alam Chowdhury, University of Texas at Austin

Special thanks: Md. Kamruzzaman, EPS


题意:给出一个有向图,问第k短路是多长,相同长度但是路径不同的话,当做不同的第k短路。

思路:和always late 差不多,用一个dfs统计当前路径长度下有多少路径成立,再有一个dfs找出下一个长一点的短路,然后继续,直到k<=0 输出答案。

代码:
#include<iostream>
#include<vector>
#include<cstring>
#include<string.h>
using namespace std;
const int maxn = 110;
const int inf = 1e8;
int floyd[maxn][maxn];
int n , m , k , ptr , limit , ans;
bool flag;
struct Node
{
	int v , w;
	Node *next;
}edge[1010],*first[maxn];

void init()
{
	memset(first,0,sizeof(first));
	for (int i = 1 ; i <= n ; ++i) 
		for (int j = 1 ; j <= n ; ++j)
			floyd[i][j] = inf;
	ptr = 0;
}

void add(int x,int y,int w)
{
	edge[++ptr].v = y;
	edge[ptr].w = w;
	edge[ptr].next = first[x];
	first[x] = &edge[ptr];
}

void input()
{
	while (m--)
	{
		int u , v , w;
		scanf("%d%d%d",&u,&v,&w);
		floyd[u][v] = min(floyd[u][v],w);
		add(u,v,w);
	}
	for (int k=1;k<=n;++k)
		for (int i=1;i<=n;++i)
			for (int j=1;j<=n;++j)
				floyd[i][j] = min(floyd[i][j],floyd[i][k]+floyd[k][j]);

}

int dfs(int s,int t,int x,int dist)
{
	if (x==t && dist==ans) return 1;
	if (dist+floyd[x][t] > ans) return 0;
	int ret = 0;
	for (Node * p = first[x] ; p ; p=p->next)
	{
		int y = p->v , w = p->w;
		ret += dfs(s,t,y,dist+w);
	}
	return ret;
}

void dfs2(int s,int t,int x,int dist)
{
	if (x==t && dist < limit && dist > ans) limit = dist;
	if (dist + floyd[x][t] >= limit) return;
	if (dist+floyd[x][t] > ans) limit = dist+floyd[x][t];
	for (Node * p = first[x] ; p ; p=p->next) dfs2(s,t,p->v,dist+p->w);
}

void solve(int s , int t)
{
	if (floyd[s][t]==inf) { printf("-1\n"); return; }
	ans = floyd[s][t];
	k -= dfs(s,t,s,0);
	while (k > 0) {
		limit = inf;
		dfs2(s,t,s,0);
		if (limit==inf) { printf("-1\n"); return; }
		ans = limit;
		k -= dfs(s,t,s,0);
	}
	printf("%d\n",ans);
}

int main()
{
	while (scanf("%d%d",&n,&m),n+m)
	{
		int s , t;
		scanf("%d%d%d",&s,&t,&k);
		init();
		input();
		solve(s,t);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值