zoukankan      html  css  js  c++  java
  • LOJ#10064. 「一本通 3.1 例 1」黑暗城堡

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

    题目描述

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

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

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

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

    要求对于所有整数$i(1le ile N)$,有$S_i= D_i$成立。

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

    输入格式

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

    第二行到第$M+1$行为$3$个由空格隔开的整数$x, y, l$:表示$x$号房间与$y$号房间之间的通道长度为$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$。

    数据范围与提示

    对于全部数据,$1le Nle 1000$,$1le Mle frac{N(N-1)}{2}$,$1le lle 200$。


    题解Here!

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

    然后开始$YY$。。。

    首先一发最短路没的说。

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

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

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

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

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

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

    答案可以表示成:$$Ans=prod_{i=2}^n indegree[i]$$

    然后就没了。

    记得开$long long$。

    附代码:

    #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
    ",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;
    }
    
  • 相关阅读:
    改善深层神经网络
    IO操作 第一篇 学习(转载)
    杂谈:收集的一些博文
    杭电2072
    Java数组常用方法
    JAVA中final修饰符小结
    南阳106
    南阳283
    南阳277
    南阳458
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9931474.html
Copyright © 2011-2022 走看看