poj-3463 Sightseeing

原创 2015年07月06日 21:02:28

题意:
给出一个n点m边的有向图,求s到t的最短路和长度为最短路+1的路的种类数;

n<=1000,m<=10000;


题解:

对于长度仅为最短路+1的路,处理时我们可以放宽一些限制;

只需求最短路和次短路,然后判断一下次短路是否满足情况就好了;

那么,求最短路+次短路的算法就用dij来处理;

令:

dis[x][k]表示x点的最短路次短路长度;

cnt[x][k]表示x点的最短路次短路分别的种类数;

vis[x][k]表示在dij算法中已经固定了的点,不会再次被更新;

k∈{0,1},分别表示最短路和次短路;

然后每次找出所以路中最小的一个,更新所有可到达的点;

分情况讨论累计种类数,就可以得到答案了;


HINT:

1.实际上dij时因为n较小,用heap实现也是可以的,但是代码比较麻烦,所以直接枚举O(n^2)

2.至于用dij而不用spfa是因为dij算法每个结点只会对其它结点进行一次更新;

   spfa可能多次入队多次更新造成计数错误,但是记录一些东西也是可以做的;

3.dij的循环要执行2*n次因为有2*n个vis数组要更新;


代码:


#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 1100
using namespace std;
vector<int>to[N], val[N];
int dis[N][2], cnt[N][2];
int vis[N][2];
void init(int n)
{
	for (int i = 1; i <= n; i++)
		to[i].clear(),
		val[i].clear();
	memset(vis, 0, sizeof(vis));
	memset(cnt, 0, sizeof(cnt));
	memset(dis, 0x3f, sizeof(dis));
}
void Dij(int n)
{
	int s, t, i, j, k, x, y;
	bool fl;
	scanf("%d%d", &s, &t);
	dis[s][0] = 0;
	cnt[s][0] = 1;
	for (i = 1; i <= 2 * n; i++)
	{
		k = 0x3f3f3f3f;
		for (j = 1; j <= n; j++)
		{
			if (!vis[j][0] && dis[j][0] < k)
				x = j, fl = 0, k = dis[j][0];
			else if (!vis[j][1] && dis[j][1] < k)
				x = j, fl = 1, k = dis[j][1];
		}
		if (k == 0x3f3f3f3f)
			break;
		vis[x][fl] = 1;
		for (j = 0; j < to[x].size(); j++)
		{
			y = to[x][j];
			if (dis[y][0]>k + val[x][j])
			{
				dis[y][1] = dis[y][0], cnt[y][1] = cnt[y][0];
				dis[y][0] = k + val[x][j], cnt[y][0] = cnt[x][fl];
			}
			else if (dis[y][0] == k + val[x][j])
				cnt[y][0] += cnt[x][fl];
			else if (dis[y][1] > k + val[x][j])
				dis[y][1] = k + val[x][j], cnt[y][1] = cnt[x][fl];
			else if (dis[y][1] == k + val[x][j])
				cnt[y][1] += cnt[x][fl];
		}
	}
	if (dis[t][1] == dis[t][0] + 1)
		cnt[t][0] += cnt[t][1];
	printf("%d\n", cnt[t][0]);
}
int main()
{
	int c, T, n, m, i, j, k, x, y, v;
	scanf("%d", &T);
	for (c = 1; c <= T; c++)
	{
		scanf("%d%d", &n, &m);
		init(n);
		for (i = 1; i <= m; i++)
		{
			scanf("%d%d%d", &x, &y, &v);
			to[x].push_back(y);
			val[x].push_back(v);
		}
		Dij(n);
	}
	return 0;
}


poj 3463 最短路与次短路

非常好的题目 “可能存在多条路径的情况下” 求解从指定源点到汇点的最短路和次短路 dijkstra框架结构基本不变,松弛的时候才用以下方式 /* 求s到t的最短路与次短路(这里要求只...
  • cfzjxz
  • cfzjxz
  • 2013年01月09日 16:30
  • 1722

poj 3621 Sightseeing Cows(最优比例生成环,01分数规划)

http://poj.org/problem?id=3621 大致题意:给出一个有向图,每个点都有一个点权,每条有向边也都有一个边权,要求出一个环使得环中点权之和与边权之和的比值最大。 ...
  • u013081425
  • u013081425
  • 2014年05月27日 19:56
  • 1096

POJ 难度及题型题目分类

OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094) 初期:...
  • u010871244
  • u010871244
  • 2013年07月16日 10:34
  • 1930

【POJ】3463 Sightseeing 最短路+比最短路大一的路(最短路 or 最短路+DP)

Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6951   Ac...
  • u013368721
  • u013368721
  • 2014年07月03日 19:09
  • 622

POJ 3463 Sightseeing Dijkstra最短路&最短路-1的路径数(计数)

题目大意:求给定的DAG中最短路&z
  • Orzmyk
  • Orzmyk
  • 2014年08月25日 21:49
  • 358

poj 3463 Sightseeing(最短路&&次短路)

Language: Default Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Su...
  • u011699990
  • u011699990
  • 2015年05月14日 01:08
  • 477

POJ 3463 Sightseeing 最短路+次短路

题意:给定一个有向图,问从起点到终点,最短路+比最短路距离长1的路的个数。 思路:最短路+次短路。 #include #include #include #include #inclu...
  • kdqzzxxcc
  • kdqzzxxcc
  • 2012年09月19日 18:15
  • 730

POJ 3463 Sightseeing (第k短路)

~~题目链接~~~ 题目大意:给出一个旅游路线,现在要求求它的最短路和比最短路长1的路共有多少条。 思路:看代码吧 #include #include #define...
  • ulquiorra0cifer
  • ulquiorra0cifer
  • 2012年09月05日 13:49
  • 1151

POJ-3463: Sightseeing 【最短路次短路及条数】

Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9247   Ac...
  • swust_Three
  • swust_Three
  • 2017年04月19日 20:56
  • 132

poj 3463 Sightseeing (dij 求最短路和次短路并计数)

dijkstra求最短路和次短路的求法和计算  模板 dijkstra求最短路的变形。 外循环要循环2*n-1次,因为dis[n][2]有2*n个状态,而dis[s][0]已经用过一次。 ...
  • u012841845
  • u012841845
  • 2014年07月08日 23:11
  • 977
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj-3463 Sightseeing
举报原因:
原因补充:

(最多只允许输入30个字)