Typesetting math: 100%

LOJ#10064. 「一本通 3.1 例 1」黑暗城堡

LOJ#10064. 「一本通 3.1 例 1」黑暗城堡

题目描述

你知道黑暗城堡有N个房间,M条可以制造的双向通道,以及每条通道的长度。

城堡是树形的并且满足下面的条件:

Di为如果所有的通道都被修建,第i号房间与第1号房间的最短路径长度;

Si为实际修建的树形城堡中第i号房间与第1号房间的路径长度;

要求对于所有整数i(1iN),有Si=Di成立。

你想知道有多少种不同的城堡修建方案。当然,你只需要输出答案对2311取模之后的结果就行了。

输入格式

第一行为两个由空格隔开的整数N,M;

第二行到第M+1行为3个由空格隔开的整数x,y,l:表示x号房间与y号房间之间的通道长度为l

输出格式

一个整数:不同的城堡修建方案数对2311取模之后的结果。

样例

样例输入

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号房间之间的通道长度分别为123121

而不同的城堡修建方案数对2311取模之后的结果为6

数据范围与提示

对于全部数据,1N10001MN(N1)21l200


题解Here!

据说标解是最短路径树?但是本蒟蒻不会啊。。。

然后开始YY。。。

首先一发最短路没的说。

我直接SPFA的,出题人良心,没有卡SPFA

然后把所有可能在生成树上的边提出来。

我们会发现这些边形成了一个DAG

然后对于每个点(除了1),我们一定至少有一种选择方案,将它挂在某个节点的下面,成为儿子节点。

所以我们把这些点的选择方案数乘起来就是我们的答案。

而每个点i的选择方案就是这个点在DAG中的入度indegree[i]

答案可以表示成:Ans=ni=2indegree[i]

然后就没了。

记得开long long

附代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#define MAXN 1010
#define MAX 999999999
#define MOD 2147483647LL
using namespace std;
int n,m,c=1;
int head[MAXN],path[MAXN];
long long ans=1,indegree[MAXN];
bool vis[MAXN];
struct Grpah{
    int next,to,w;
}edge[MAXN*MAXN];
inline int read(){
    int date=0,w=1;char c=0;
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    return date*w;
}
inline int relax(int u,int v,int w){
    if(path[v]>path[u]+w){
        path[v]=path[u]+w;
        return 1;
    }
    return 0;
}
inline void add_edge(int u,int v,int w){
    edge[c].to=v;edge[c].w=w;edge[c].next=head[u];head[u]=c++;
    edge[c].to=u;edge[c].w=w;edge[c].next=head[v];head[v]=c++;
}
void spfa(){
    int u,v;
    queue<int> q;
    for(int i=1;i<=n;i++){path[i]=MAX;vis[i]=false;}
    path[1]=0;
    vis[1]=true;
    q.push(1);
    while(!q.empty()){
        u=q.front();
        q.pop();
        vis[u]=false;
        for(int i=head[u];i;i=edge[i].next){
            v=edge[i].to;
            if(relax(u,v,edge[i].w)&&!vis[v]){
                vis[v]=true;
                q.push(v);
            }
        }
    }
}
void work(){
    int u,v,w;
    for(int i=1;i<c;i+=2){
        u=edge[i+1].to;v=edge[i].to;w=edge[i].w;
        if(path[u]+w==path[v])indegree[v]++;
        if(path[v]+w==path[u])indegree[u]++;
    }
    for(int i=2;i<=n;i++)ans=ans*indegree[i]%MOD;
    printf("%lld\n",ans);
}
void init(){
    int u,v,w;
    n=read();m=read();
    for(int i=1;i<=m;i++){
        u=read();v=read();w=read();
        add_edge(u,v,w);
    }
    spfa();
}
int main(){
    init();
    work();
    return 0;
}

 

posted @   符拉迪沃斯托克  阅读(498)  评论(0编辑  收藏  举报
编辑推荐:
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
阅读排行:
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· 软件产品开发中常见的10个问题及处理方法
· Vite CVE-2025-30208 安全漏洞
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(四):结合BotSharp
· MQ 如何保证数据一致性?
Live2D
欢迎阅读『LOJ#10064. 「一本通 3.1 例 1」黑暗城堡』
点击右上角即可分享
微信分享提示