16.1113 模拟考试T3
2016-11-13 15:57
337 查看
城堡
【问题描述】
给定一张N个点M条边的无向连通图,每条边有边权。我们需要从M条边中
选出N − 1条, 构成一棵树。 记原图中从 1 号点到每个节点的最短路径长度为?Di ,
树中从 1 号点到每个节点的最短路径长度为Si ,构出的树应当满足对于任意节点
i,都有Di = Si 。
请你求出选出N − 1条边的方案数。
【输入格式】
输入的第一行包含两个整数N和M。
接下来M行,每行包含三个整数u、v和w,描述一条连接节点u和v且边权为
w的边。
【输出格式】
输出一行,包含一个整数,代表方案数对2^31 − 1取模得到的结果。
【样例输入】
3 3
1 2 2
1 3 1
2 3 1
【样例输出】
2
【数据规模和约定】
对于30%的数据 2 ≤ N ≤ 5,M ≤ 10。
对于50%的数据,满足条件的方案数不超过 10000。
对于100%的数据,2≤ N ≤ 1000,N − 1 ≤ M ≤
N(N−1)/2,
1 ≤ w ≤ 100。
思路:两遍SPFA,第一遍求出dis[],第二遍的时候求出没个点可以有几条最短路得来,(++c[i]),之后,根据乘法原理,c数组全部乘起来并且取模。
【问题描述】
给定一张N个点M条边的无向连通图,每条边有边权。我们需要从M条边中
选出N − 1条, 构成一棵树。 记原图中从 1 号点到每个节点的最短路径长度为?Di ,
树中从 1 号点到每个节点的最短路径长度为Si ,构出的树应当满足对于任意节点
i,都有Di = Si 。
请你求出选出N − 1条边的方案数。
【输入格式】
输入的第一行包含两个整数N和M。
接下来M行,每行包含三个整数u、v和w,描述一条连接节点u和v且边权为
w的边。
【输出格式】
输出一行,包含一个整数,代表方案数对2^31 − 1取模得到的结果。
【样例输入】
3 3
1 2 2
1 3 1
2 3 1
【样例输出】
2
【数据规模和约定】
对于30%的数据 2 ≤ N ≤ 5,M ≤ 10。
对于50%的数据,满足条件的方案数不超过 10000。
对于100%的数据,2≤ N ≤ 1000,N − 1 ≤ M ≤
N(N−1)/2,
1 ≤ w ≤ 100。
1 #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; const int N=1000; const int M=499500; const int INFI=12345678; const ll mod = (1LL<<31)-1LL; struct node{ int next,node,w; }e[M*2]; ll c[N+1],ans; int n,m,x,y,w,head[N+1],tot,dis[N+1]; bool exist[N+1]; void add_edge(int a,int b,int w){ e[++tot].next=head[a]; head[a]=tot;e[tot].node=b;e[tot].w=w; } inline void SPFA(int s) { queue<int> que; for(int i=1;i<=n;i++) dis[i]=0x3f; dis[s]=0;exist[s]=true;que.push(s); while(!que.empty()) { int cur=que.front(); exist[cur]=false;que.pop(); for(int i=head[cur];i;i=e[i].next) { int node=e[i].node; if(dis[node]>dis[cur]+e[i].w){ dis[node]=dis[cur]+e[i].w; if(!exist[node]) exist[node]=true,que.push(node); } } } } int main() { freopen("castle.in","r",stdin); freopen("castle.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&w);add_edge(x,y,w);add_edge(y,x,w); } SPFA(1); queue<int> q;q.push(1),exist[1]=true,c[1]=1LL; while(!q.empty()){ int cur=q.front();q.pop(); for(int i=head[cur];i;i=e[i].next){ int node=e[i].node; if(dis[node]==dis[cur]+e[i].w){ ++c[node]; if(c[node]>=mod) c[node]-=mod; if(!exist[node]) q.push(node),exist[node]=true; } } } ans=1LL; for(int i=1;i<=n;i++){ ans*=c[i]; if(ans>=mod) ans%=mod; } printf("%d",(int)ans); fclose(stdin); fclose(stdout); return 0; }
思路:两遍SPFA,第一遍求出dis[],第二遍的时候求出没个点可以有几条最短路得来,(++c[i]),之后,根据乘法原理,c数组全部乘起来并且取模。
相关文章推荐
- 16.1113 模拟考试T3
- 16.1113 模拟考试T1
- 16.1113 模拟考试T2
- 16.1113 模拟考试T2
- 2016普及组模拟考试 01题
- NOIP2016年普及组模拟考试(9.3) 1.笨笨玩游戏
- 计算机等级考试训练模拟软件(一级b) 下载
- 模拟考试9.3-笨笨的西瓜种植(watermelon.cpp)
- 2016年江西理工大学第一轮模拟考试
- 大学计算机模拟考试常见试题与解析(二)
- 20160930的考试,noip模拟】SPFA,LIS,状压dp
- 【NOIP模拟题】T3 【递归】【复杂公式】【模拟】
- [置顶] [模拟考试题][神题]Star Sky[状压DP][BFS][差分]
- jQuyer模拟在线考试做题
- XTU 程序设计实践模拟考试题1
- 1109 NOIP 模拟考试
- 某交规模拟考试系统验证绕路手记
- 【2016普及组模拟考试】04 搜索 tribe(部落卫队)
- 期中模拟考试 题解
- 计算机等级考试训练模拟软件(三级网络技术) 下载