BZOJ 5056 OI游戏 (最短路径树)

来源:互联网 发布:2012年梅西进球数据 编辑:程序博客网 时间:2024/06/06 00:11

5056: OI游戏

Time Limit: 1 Sec Memory Limit: 64 MB
Description

小Van的CP最喜欢玩与OI有关的游戏啦~小Van为了讨好她,于是冥思苦想,终于创造了一个新游戏。
下面是小Van的OI游戏规则:
给定一个无向连通图,有N个节点,编号为0~N-1。图里的每一条边都有一个正整数权值,边权在1~9之间。
要求从图里删掉某些边(有可能0条),使得剩下的图满足以下两个条件:
1) 剩下的图是一棵树,有N-1条边。
2) 对于所有v (0 < v < N),0到v的最短路(也就是树中唯一路径长度)和原图中的最短路长度相同。
最终要报出有多少种不同的删法可以满足上述条件。(两种删法不同当且仅当存在两个点,
一种删法删完之后这两个点之间存在边而另外一种删法不存在。)
由于答案有可能非常大,良心的小Van只需要答案膜1,000,000,007的结果。
后记: 然而这游戏太高难度了,小Van的CP做不出来因此很不开心!
她认为小Van在故意刁难她,于是她与小Van分手了。。。
不过对于精通OI的你来说,这不过是小菜一碟啦!

Input

第一行一个整数N,代表原图结点。
接下来N行,每行N个字符,描绘了一个邻接矩阵。邻接矩阵中,
如果某一个元素为0,代表这两个点之间不存在边,
并且保证第i行第i列的元素为0,第i行第j列的元素(i≠j)等于第j行第i列的元素。
2≤N≤50

Output

一行一个整数,代表删法总方案数膜1,000,000,007的结果。

Sample Input

Input1

2
01
10

Input2

4
0123
1012
2101
3210

Sample Output

Output1

1

Output2

6

题意:
求最小路径树计数。

题解:
直接spfa,求出每个点的最短路径上的边数目乘起来就可以了。
感性理解。。。

#include <cstdio>#include <cstring>#include <iostream>#include <queue>#include <algorithm>#define LL long long#define mod 1000000007#define N 55using namespace std;queue<int> q;int n;struct Edge{    int u, v, w, nxt;}ed[3010];int head[N], idc=0;char ss[N];int dis[N];bool vis[N];void adde(int u, int v, int w){    ed[++idc].u = u;    ed[idc].v = v;    ed[idc].w = w;    ed[idc].nxt = head[u];    head[u] = idc; }int main(){    scanf("%d", &n);    for(int i=1; i<=n; i++){        scanf("%s", ss+1);        for(int j=1; j<=n; j++)            if(ss[j] != '0') adde(i, j, ss[j]-'0');    }    memset(dis, 63, sizeof(dis));    dis[1] = 0; vis[1] = 1;    q.push( 1 );    while(!q.empty()){        int u = q.front(); q.pop();        vis[u] = 0;        for(int i=head[u]; i; i=ed[i].nxt){            int v = ed[i].v;            if(dis[v] > dis[u] + ed[i].w){                dis[v] = dis[u] + ed[i].w;                if( !vis[v] ) vis[v] = 1, q.push(v);            }        }    }    LL ans = 1;    for(int u=2; u<=n; u++){//root会被之后的统计到         LL tot = 0;        for(int i=head[u]; i; i=ed[i].nxt){            int v = ed[i].v;            if(dis[u] == dis[v] + ed[i].w) tot++;        }//取这tot个路径都可以保证u还有最短路径         (ans *= tot) %= mod;    }    printf("%lld", ans);    return 0;}
原创粉丝点击