城堡(统计最短路数问题)

来源:互联网 发布:淘宝网婴儿用品 编辑:程序博客网 时间:2024/06/10 13:15

城堡

问题描述:
给定一张n个点m条边的无向连通图,每条边有边权。我们需要从m条边中
选出n−1条,构成一棵树。记原图中从 1 号点到每个节点的最短路径长度为di,树中从 1 号点到每个节点的最短路径长度为? ? ,构出的树应当满足对于任意节点si,都有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。

#include<iostream>#include<cstdio>#include<queue>#define lon long longusing namespace std;const int maxn=10010;const long long mod=0x7fffffff;lon n,m,tot,c[maxn],head[maxn],dis[maxn];bool flag[maxn];struct node{    lon to;    lon from;    lon w;    lon next;}e[1000010];lon init(){    lon x=0,f=1;char c=getchar();    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}    return x*f;}void add_edge(lon u,lon v,lon w){    e[++tot].to=v;    e[tot].from=u;    e[tot].w=w;    e[tot].next=head[u];    head[u]=tot;}void spfa(){    for(lon i=1;i<=n;i++)    dis[i]=0x7fffffff;dis[1]=0;    queue<lon> q;    q.push(1);flag[1]=1;    while(!q.empty())    {        lon u=q.front();        q.pop();flag[u]=0;        for(lon i=head[u];i;i=e[i].next)        {            lon v=e[i].to;            if(dis[v]>dis[u]+e[i].w)            {                dis[v]=dis[u]+e[i].w;                if(!flag[v])                {                    q.push(v);                    flag[v]=1;                }            }        }    }}int main(){    freopen("castle.in","r",stdin);    freopen("castle.out","w",stdout);    lon x,y,z;    n=init();m=init();    for(lon i=1;i<=m;i++)    {        x=init();y=init();z=init();        add_edge(x,y,z);        add_edge(y,x,z);    }    spfa();    lon ans=1;    for(int i=1;i<=tot;i++)    {        lon u=e[i].from;        lon v=e[i].to;        if(dis[v]==dis[u]+e[i].w)        c[v]++;    }    for(int i=2;i<=n;i++)    ans=(ans*c[i])%mod;    cout<<ans;    fclose(stdin);fclose(stdout);    return 0;}
1 0
原创粉丝点击