前言:好吧实际题目是这样的→CH 6202 黑暗城堡
题目:
分析:
对于题目中的
D
D
D,我们可以通过
D
I
J
+
DIJ+
DIJ+堆优化高效求解
然后跑一边伪
p
r
i
m
e
prime
prime,将判断最小生成树的条件换成题目要求我们保持的那一长串东东,同时对该点的方案数进行累加
最后根据乘法原理,将所有点的方案数累乘
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
#define ch cheap
#define mo (1LL<<31)-1
#define ppp pair <int,int>
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int ls[999000];
struct node{
int to,next,w;
}e[999000];
priority_queue<ppp,vector<ppp>,greater<ppp> > q;
int cnt;
void add(int x,int y,int w)
{
e[cnt]=(node){y,ls[x],w};
ls[x]=cnt++;
return;
}
struct dij{
int id,w;
}d[1005];
int tf[1005],dis[1005];
void Dij()
{
q.push(make_pair(0,1));
memset(tf,0,sizeof(tf));
for(int i=1;i<=1000;i++) d[i].w=99999999;
d[1].w=0;
while(q.size())
{
int u=q.top().second;q.pop();
if(tf[u]) continue;
tf[u]=1;
for(int i=ls[u];~i;i=e[i].next)
if(d[e[i].to].w>d[u].w+e[i].w)
d[e[i].to].w=d[u].w+e[i].w,q.push(make_pair(d[e[i].to].w,e[i].to));
}
return;
}
bool cmp(dij a,dij b) {return a.w<b.w;}
LL p[1005],ans=0;
int main()
{
memset(ls,-1,sizeof(ls));
int n=read(),m=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),w=read();
add(x,y,w);add(y,x,w);
}
Dij();
for(int i=1;i<=n;i++) d[i].id=i,dis[i]=d[i].w;
sort(d+1,d+1+n,cmp);
memset(tf,0,sizeof(tf));
tf[1]=1;
for(int i=2;i<=n;i++)
{
tf[d[i].id]=1;
for(int j=ls[d[i].id];~j;j=e[j].next)
{
int v=e[j].to;
if(tf[v]&&dis[v]+e[j].w==d[i].w)
p[i]++;
}
}
ans=1;
for(int i=2;i<=n;i++) (ans*=p[i])%=mo;
cout<<ans;
return 0;
}