黑暗城堡
Posted akaina
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了黑暗城堡相关的知识,希望对你有一定的参考价值。
题意:有(n)个点,(m)条边,设(D[i])位第(i)号房间与第(1)号房间的最短路径长度,(S[i])位实际生成树中第(i)号房间与第(1)号房间的路径长度,要求对于所有整数(i),都有(S[i] = D[i])成立,求生成树的方案数。
解法:先用(Dijkstra)求出(1)号房间到每个房间的最短路长度,然后按(dis)排序(可以不用排序,因为只能从小的边权得到大的边权),利用类似(Prim)的思想,算出集合(S)连向集合(T)中(v)点,使得(dis[v] = dis[T]+ edg[i])的边数,然后利用乘法原理计算方案数即可。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
#define maxn 1010
#define maxm 1000100
#define mp make_pair
#define pr pair<int, int>
int n, m;
int fir[maxn], nxt[maxm], vv[maxm];
long long edg[maxm];
int tot = 0;
void add(int u, int v, long long w)
{
nxt[++tot] = fir[u];
fir[u] = tot;
vv[tot] = v;
edg[tot] = w;
}
long long dis[maxn];
priority_queue<pr, vector<pr>, greater<pr> > q;
void dijkstra(int x)
{
memset(dis, 0x3f, sizeof(dis));
dis[x] = 0;
q.push(mp(0, x));
while(!q.empty())
{
pr tmp = q.top(); q.pop();
int u = tmp.second;
for(int i = fir[u]; i; i = nxt[i])
{
int v = vv[i];
if(dis[v] > dis[u] + edg[i])
{
dis[v] = dis[u] + edg[i];
q.push(mp(dis[v], v));
}
}
}
}
#define mol 2147483647
long long ans = 1;
int d[maxn], cnt = 0;
long long sum[maxn];
void prim()
{
d[++cnt] = 1; d[1] = 0; sum[1] = 1;
for(int i = 1; i <= n; i++)
{
for(int j = fir[i]; j; j = nxt[j])
if(dis[vv[j]] == dis[i] + edg[j]) sum[vv[j]]++;
}
for(int i = 1; i <= n; i++) ans = ans * sum[i] % mol;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
{
int u, v; long long w;
scanf("%d%d%lld", &u, &v, &w);
add(u, v, w); add(v, u, w);
}
dijkstra(1);
prim();
printf("%lld
", ans);
return 0;
}
以上是关于黑暗城堡的主要内容,如果未能解决你的问题,请参考以下文章