//poj3463 次短路计数
/*
由于次短路条数可能很多,如果使用k短路算法将超时
使用djikstra算法
dijkstra性质:
1.每个点只会更新其他点一次,之后便不会被其他点更新。
2.重边不影响。
有几点注意事项:
0.先求出最短路,再求次短路。
1.维护每个点的最短路恒小于次短路。所以,为了做到这点,每次更新时优先更新最短路,
否则才更新次短路。
2.将状态节点插入堆中时要分两种情况:0代表该点的最短路得到更新,1代表改点的次短路的情况得到更新。
3.由于dijisktra的性质,该题中,一个点至多把周围点松弛2次,分别更新周围点的最短路和次短路。所以,
如果松弛时发现后继点的距离与前驱点加距离的和相等,只进行计数操作,后继点不用进堆(这意味着后继点还没
松弛其他点)同时,由于这道题的要求是计数,需要用vis维护每个点只松弛周围点一次,否则会造成重复计数。

需要加强对dijkstra、spfa、floyd的理解,以便熟练改造
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define ll long long 
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
#define pb(a) push_back(a)
const int MAXN=1005;
const int MAXM=10005;
int n,m,k;
int cases;
struct edge{
	int f,t,d;
};
struct point{
	int n,d,p;
	bool operator<(const point &a)const{
		return d>a.d;
	}
};

struct dijkstra{
	int s,t;
	vector<int>g[MAXN];
	vector<edge>e;
	int d[MAXN],dd[MAXN];
	int cond[MAXN],condd[MAXN];
	bool vis[MAXN][2];
	void init(){
		fr(i,0,MAXN-1)
			g[i].clear();
		e.clear();
	}
	void add_edge(int f,int t,int d){
		e.push_back((edge){f,t,d});
		g[f].push_back(e.size()-1);
	}
	int solve(){
		ms(vis,false);
		ms(cond,0);
		ms(condd,0);
		fr(i,0,MAXN-1)
			dd[i]=d[i]=214748360;
		d[s]=0;cond[s]=1;
		priority_queue<point>q;
		q.push((point){s,0,0});
		while(!q.empty()){
			point now=q.top();
			q.pop();
			int s=now.n,p=now.p;
			if(vis[s][p])
				continue;
			vis[s][p]=true;
			int size=g[s].size();
			fr(i,0,size-1){
				edge ne=e[g[s][i]];
				int t=ne.t;
				//printf("t=%d\n",t);
				if(p==0){
					if(d[t]>d[s]+ne.d){//直接将最短路的数据给次短路。不用考虑s点的次短路,因为如果s点的次短路得到更新,那么后面t的次短路会在p==1时处理
						dd[t]=d[t];
						condd[t]=cond[t];
						d[t]=d[s]+ne.d;
						cond[t]=cond[s];
						q.push((point){t,d[t],0});
						q.push((point){t,dd[t],1});
					}
					else if(d[t]==d[s]+ne.d)
						cond[t]+=cond[s];
					else if(dd[t]>d[s]+ne.d){
						dd[t]=d[s]+ne.d;
						condd[t]=cond[s];
						q.push((point){t,dd[t],1});
					}
					else if(dd[t]==d[s]+ne.d)
						condd[t]+=cond[s];
				}
				else{
					if(dd[t]>dd[s]+ne.d){
						dd[t]=dd[s]+ne.d;
						condd[t]=condd[s];
						q.push((point){t,dd[t],1});
					}
					else if(dd[t]==dd[s]+ne.d)
						condd[t]+=condd[s];
				}
			}
		}
		int ans=0;
		if(d[t]==dd[t]-1)
			ans=condd[t];
		ans+=cond[t];
		return ans;
	}
	
}kth;
int main(){
	//ios::sync_with_stdio(false);
	scfd(&cases);
	while(cases--){
		scanf("%d%d",&n,&m);
		kth.init();
		fr(i,1,m){
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			kth.add_edge(a,b,c);
		}
		scanf("%d%d",&kth.s,&kth.t);
		ptfd(kth.solve());
	}
	return 0;
}
 posted on 2017-09-22 16:58  cylcy  阅读(135)  评论(0编辑  收藏  举报