poj 3463 统计次短路条数+最短路条数

题意:给一个有向图,问从s到t的     最短路  和    比最短路距离长1的次短路 
思路:Dijkstra(不使用heap)
1.每次维护次短路和最短路的长度,与最短路和次短路的条数
最后输出结果的时候判断当前最短路和次短路的长度差是否为1
2.维护方法:
dis[i][0]:到点i的最短路长度  dis[i][1]:到i点的次短路长度
cnt[i][0]:到点i的最短路的路数   cnt[i][1]:到i点的最短路条数
vis表示最短路或次短路是否已经算出 
每次找到和当前集合中距离最近的点加入集合
先更新最短路,如果小于原来的路径,将原来的最短路设为次短路,将新加入的点设为最短路
如果和最短路相等,直接将新加入点的方案数累加到原来的方案数中;
如果不能更新最短路,再更新次短路,更新步骤同上
总之 if balala else blala if blala else blala.......


代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cassert>
#include <sstream>
#include <numeric>
#include <climits>
#include <string>
#include <cctype>
#include <ctime>
#include <iomanip>
#include <cmath>
#include <vector>
#include <queue>
#include <list>
#include <map>
#include <set>
#define INF 29000
#define MAX 1000000000
using namespace std;
struct data{
	int to,len,next;
}bian[2*INF];
int t,size,first[INF],casee;
int vis[INF][2],cnt[INF][2],dis[INF][2];
int n,m,x,y,z,s;
//dis[i][0]:到点i的最短路  dis[i][1]次短路 
//cnt[i][0]:到点i的最短路的路数 
//vis表示最短路或次短路是否已经算出 
void add(int x,int y,int z)
{
	size++;
	bian[size].next=first[x];
	first[x]=size;
	bian[size].to=y;
	bian[size].len=z;
}
void Dijkstra(int s,int t)
{
	
	dis[s][0]=0;
	cnt[s][0]=1;
	int maxx,pos,flag;
	for(int i=1;i<=2*n-1;i++)
	{
		int minn=MAX;
		for(int j=1;j<=n;j++)
		{
			if(!vis[j][0]&&minn>dis[j][0])
			{
				minn=dis[j][0];
				pos=j;
				flag=0;
			} 
			else
			if(!vis[j][1]&&minn>dis[j][1])
			{
				minn=dis[j][1];
				pos=j;
				flag=1;
			}
		}
		if(minn==MAX)break;
		vis[pos][flag]=1;
		for(int u=first[pos];u;u=bian[u].next)
		{
			int to=bian[u].to,len=bian[u].len;
			if(dis[to][0]>minn+len)
			{	
				dis[to][1]=dis[to][0];
				dis[to][0]=minn+len;
				cnt[to][1]=cnt[to][0];
				cnt[to][0]=cnt[pos][flag];
			}
			else 
			if(dis[to][0]==minn+len)
				cnt[to][0]+=cnt[pos][flag];
			else
			{
				if(dis[to][1]>minn+len)
				{
					dis[to][1]=minn+len;
					cnt[to][1]=cnt[pos][flag];
				}
				else 
				if(dis[to][1]==minn+len)
					cnt[to][1]+=cnt[pos][flag];
			}
		}
	}
	int ans;
	if(dis[t][0]+1==dis[t][1])
		ans=cnt[t][0]+cnt[t][1];	
	else ans=cnt[t][0];
	cout<<ans<<endl;
}
void init()
{
	memset(vis,0,sizeof(vis));
	memset(first,0,sizeof(first));
	size=0;
	for(int i=1;i<=n;i++)
		dis[i][0]=dis[i][1]=INF;
	memset(cnt,0,sizeof(cnt));
}
int main()
{
//	freopen("in.in","r",stdin);
	ios::sync_with_stdio(false);cin.tie(NULL);
	cin>>casee;
	while(casee--)
	{
		cin>>n>>m;
		init();
		for(int i=1;i<=m;i++)
		{
			cin>>x>>y>>z;
			add(x,y,z);
		}
		cin>>s>>t;
		Dijkstra(s,t);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值