/*
求s到t的最短路与次短路(这里要求只比最短路多1)的条数之和
联想到最小,次小的一种更新关系:
if(x<最小)更新最小,次小
else if(==最小)更新方法数
else if(x<次小)更新次小
else if(x==次小)更新方法数
同时记录s到u最短,次短路及方法数
用一个堆每次取最小的,更新完后再入堆
还是那个原理,第一次遇到的就是最优的,然后vi标记为真
方法数注意是加法原理,不是乘法
\
-- u -- v 所以是加法原理
/
*/
//单开一个数组来记录数目
//理解了一下。。。还要回去debug..
//http://blog.csdn.net/u013368721/article/details/36682223
#include<iostream>
#include<cstring>
#include<string.h>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define maxm 200
#define maxn 200
#define MAXN 200
#define inf 0x3f3f3f
using namespace std;
int em;
int head[maxn];
bool vis[2][maxn];
int d[maxn];
int d2[maxn];
int cnt[2][maxn];
struct Edge
{
int u,len,next;
}edge[2*MAXN];
void addEdge(int v,int w,int c)
{
edge[em].u=w;
edge[em].len=c;
edge[em].next=head[v];
head[v]=em;
em++;
}
struct Node
{
int a;
int kind;
int len;
friend bool operator <(Node a,Node b)
{
if(a.len!=b.len)
return a.len>b.len;
return a.a>b.a;//过了,但是这里为什么要按字典序排序
}
}start,v,tem;
priority_queue <Node>q;//0为最短路,1为次短路。。kind为加入的边的种类??开数组保存
void dij(int s,int t)
{
while(!q.empty()) q.pop();
for(int i=0;i<=t;i++)
d[i]=inf,d2[i]=inf,cnt[0][i]=0,cnt[1][i]=0;
memset(vis,false,sizeof(vis));
start.a=s;
start.kind=0;
start.len=0;
cnt[0][s]=1;d[s]=0;
q.push(start);
while(!q.empty())
{
v=q.top();
int u=v.a;
int dis=v.len;
int kind=v.kind;
q.pop();
if(vis[kind][u]) continue;
vis[kind][u]=1;
for(int i=head[u];~i;i=edge[i].next)
{
int vi=edge[i].u;
int tmp=dis+edge[i].len;
if(tmp<d[vi])
{
if(d[vi]<d2[vi])
{
d2[vi]=d[vi];
cnt[1][vi]=cnt[0][vi];
tem.a=vi;
tem.len=d2[vi];
tem.kind=1;
q.push(tem);
}
d[vi]=tmp;
cnt[0][vi]=cnt[0][u];
tem.a=vi;
tem.len=tmp;
tem.kind=0;
q.push(tem);
}
else if(tmp==d[vi])
{
cnt[0][vi]+=cnt[0][u];
}
else if(tmp<d2[vi])
{
d2[vi]=tmp;
cnt[1][vi]=cnt[kind][u];
tem.a=vi;
tem.len=d2[vi];
tem.kind=1;
q.push(tem);
}
else if(tmp==d2[vi])
{
cnt[1][vi]+=cnt[kind][u];
}
}
}
cout<<d2[t]<<" "<<cnt[1][t]<<endl;
}
int main()
{
// freopen("input.txt","r",stdin);
int n,m,s,a,b,e,w;
while(scanf("%d%d%d%d",&n,&m,&s,&e)!=EOF)
{
memset(head,-1,sizeof(head));
em=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&w);
addEdge(a,b,w);
}
dij(s,e);
}
}
HDU3191 次短路条数
最新推荐文章于 2020-04-10 14:07:27 发布