[LOJ#10064]黑暗城堡

Description
在顺利攻破 Lord lsp 的防线之后,lqr 一行人来到了 Lord lsp 的城堡下方。Lord lsp 黑化之后虽然拥有了强大的超能力,能够用意念力制造建筑物,但是智商水平却没怎么增加。现在 lqr 已经搞清楚黑暗城堡有 N 个房间,M 条可以制造的双向通道,以及每条通道的长度。lqr 深知 Lord lsp 的想法,为了避免每次都要琢磨两个房间之间的最短路径, Lord lsp一定会把城堡修建成树形的;但是,为了尽量提高自己的移动效率,Lord lsp 一定会使得城堡满足下面的条件:设 Di为如果所有的通道都被修建,第 i 号房间与第 1 号房间的最短路径长度;而 Si 为实际修建的树形城堡中第 i 号房间与第1 号房间的路径长度,对于所有满足 1≤i≤N 的整数 i,有 Si = Di。为了打败 Lord lsp,lqr想知道有多少种不同的城堡修建方案。于是 lqr 向 applepi 提出了这个问题。由于 applepi 还要忙着出模拟赛,所以这个任务就交给你了。当然,你只需要输出答案对 2^31 – 1 取模之后的结果就行了.

Input
第一行有两个整数 N 和 M。
之后 M 行,每行三个整数 X,Y 和 L,表示可以修建 X 和 Y 之间的一条长度为 L 的通道。
2≤N≤1000,N – 1≤M≤N(N – 1)/2,1≤L≤100

Output
输出一个整数,表示答案对 2^31 – 1 取模之后的结果。

Sample Input
3 3
1 2 2
1 3 1
2 3 1

Sample Output
2


首先求出单源最短路,然后考虑第i个点,我们可以枚举1~i-1个点,求出dis[j]+g[i][j]=dis[i]的点,然后使用乘法原理即可。由于第i个点不可能由那些dis比它大的点转移过来,因此我们要开始按dis排序

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7fffffff
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
	int x=0,f=1;char ch=getchar();
	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
	return x*f;
}
inline void print(int x){
	if (x>=10)	print(x/10);
	putchar(x%10+'0');
}
const int N=1e3,M=1e6,MOD=0x7fffffff;
struct S1{
	#define ls (p<<1)
	#define rs (p<<1|1)
	#define fa (p>>1)
	struct node{
		int x,v;
		bool operator <(const node &a)const{return v<a.v;}
	}Q[N*50+10];
	int tot;
	void insert(int x,int v){
		Q[++tot]=(node){x,v};
		int p=tot;
		while (p!=1&&Q[p]<Q[fa])	swap(Q[p],Q[fa]),p=fa;
	}
	void Delete(){
		Q[1]=Q[tot--];
		int p=1,son;
		while (ls<=tot){
			if (rs>tot||Q[ls]<Q[rs])	son=ls;
			else	son=rs;
			if (Q[son]<Q[p])	swap(Q[p],Q[son]),p=son;
			else	break;
		}
	}
}Heap;
int pre[(M<<1)+10],now[N+10],child[(M<<1)+10],val[(M<<1)+10],tot;
int g[N+10][N+10],dis[N+10],ID[N+10];
bool vis[N+10];
void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
bool cmp(const int &x,const int &y){return dis[x]<dis[y];}
void Dijkstra(int x){
	memset(dis,63,sizeof(dis));
	Heap.insert(x,dis[x]=0);
	while (Heap.tot){
		int Now=Heap.Q[1].x;
		Heap.Delete();
		if (vis[Now])	continue;
		vis[Now]=1;
		for (int p=now[Now],son=child[p];p;p=pre[p],son=child[p]){
			if (dis[son]>dis[Now]+val[p]){
				dis[son]=dis[Now]+val[p];
				Heap.insert(son,dis[son]);
			}
		}
	}
}
int main(){
	int n=read(),m=read(),Ans=1;
	memset(g,63,sizeof(g));
	for (int i=1;i<=m;i++){
		int x=read(),y=read(),z=read();
		insert(x,y,z);
		g[y][x]=g[x][y]=min(g[x][y],z);
	}
	for (int i=1;i<=n;i++)	g[i][i]=0,ID[i]=i;
	Dijkstra(1);
	sort(ID+1,ID+1+n,cmp);
	for (int i=2;i<=n;i++){
		int res=0;
		for (int j=1;j<i;j++)
			if (dis[ID[j]]+g[ID[i]][ID[j]]==dis[ID[i]])
				res++;
		Ans=1ll*Ans*res%MOD;
	}
	printf("%d\n",Ans);
	return 0;
}
posted @ 2018-10-05 20:31  Wolfycz  阅读(344)  评论(0编辑  收藏  举报