黑暗城堡(生成树)
你知道黑暗城堡有 NN个房间,MM 条可以制造的双向通道,以及每条通道的长度。
城堡是树形的并且满足下面的条件:
设 Di为如果所有的通道都被修建,第 i 号房间与第 1 号房间的最短路径长度;
而Si为实际修建的树形城堡中第 ii 号房间与第 11 号房间的路径长度;
要求对于所有整数 i (1≤i≤N),有 Si=Di 成立。
你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对 2^31−1取模之后的结果就行了。
输入
第一行为两个由空格隔开的整数 N,M;
第二行到第 M+1行为 3个由空格隔开的整数x,y,l:表示 x 号房间与 yy号房间之间的通道长度为l.
输出
一个整数:不同的城堡修建方案数对 2^31−1取模之后的结果。
样例输入
4 6
1 2 1
1 3 2
1 4 3
2 3 1
2 4 2
3 4 1
样例输出
6
提示
样例说明 一共有 4 个房间,6 条道路,其中 1 号和 2 号,1 号和 3 号,1号和 4号,2号和 3 号,2 号和 4 号,3 号和 4 号房间之间的通道长度分别为 1,2,3,1,2,1。
而不同的城堡修建方案数对2^31−1取模之后的结果为 6。
对于全部数据,1≤N≤1000,1≤M≤N(N−1)2,1≤l≤2001≤N≤1000,1≤M≤N(N−1)2,1≤l≤200。
本来好像是一道求最小生成树的个数的题
结果被我用spfa给氧化钙过去了
直接spfa求出点1到所有点的距离
然后枚举每个点u以及其相邻的点v
如果有 (e为连接的边)
那么说明能这一条边满足最后能构成最小生成树
那么num[v]++
因为乘法原理
最后把所有num乘起来就是答案了
#include<bits/stdc++.h>
using namespace std;
#define mod 2147483647
inline int read(){
char ch=getchar();
int res=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
}
int n,m,adj[1004],nxt[1000005],to[1000005],cnt,val[1000005],dis[10005],num[10005];
#define ll long long
ll ans=1;
bool vis[10005];
inline void addedge(int u,int v,int w){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,val[cnt]=w;
}
inline void spfa(){
memset(dis,127,sizeof(dis));
dis[1]=0;
memset(vis,false,sizeof(vis));
queue<int> q;
q.push(1);
while(!q.empty()){
int u=q.front();
q.pop(),vis[u]=false;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(dis[v]>dis[u]+val[e])
{
dis[v]=dis[u]+val[e];
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
addedge(u,v,w);
}
spfa();
for(int u=1;u<=n;u++){
for(int e=adj[u];e;e=nxt[e]){
if(dis[u]+val[e]==dis[to[e]]){
num[to[e]]++;
}
}
}
for(int i=2;i<=n;i++)
{
ans*=num[i];
ans%=mod;
}
cout<<ans<<endl;
}