HDU 6026 Deleting Edges

来源:互联网 发布:917发卡软件下载 编辑:程序博客网 时间:2024/05/22 04:56

Little Q is crazy about graph theory, and now he creates a game about graphs and trees.
There is a bi-directional graph with n nodes, labeled from 0 to n−1. Every edge has its length, which is a positive integer ranged from 1 to 9.
Now, Little Q wants to delete some edges (or delete nothing) in the graph to get a new graph, which satisfies the following requirements:
(1) The new graph is a tree with n−1 edges.
(2) For every vertice v(0

题意

对于给定的图(双向路),有多少种子图,使其满足下列条件:

  • 子图为含 n-1 条边的树。
  • 对于任意一点 v ,子图中 0 到 v 的距离等于原图 0 到 v 的最小距离

解题思路

首先对于原图处理出 0 到任意点的最小距离。

对于子树个数的判断,可以作如下思考:

对于到 0 的最小距离最小的 m 个点,剩下的 n-m 个点的距离必然大于等于 m 个点中的任意一点,即 n-m 个点中的任意一点 p 可以通过 m 个点中的一个或多个点 q 向其连边进行扩展。其中若 dis[0][q] + src[q][p] == dis[0][p] ,则表明 p 点可以通过与 q 点连边进行扩展,cnt[p] 表示 p 点有多少种向 m 点集合并的方式

如此将此 m 个点的集合不断扩展,直到 n 个点都属于这个集合。

对于答案,即为每个点向点集中合并的方案数的积,n1i=0cnt[i]

代码

#include<bits/stdc++.h>using namespace std;const int mod = 1e9 + 7;int n, src[55][55], dis[55][55], cnt[55];char s[55][55];bool vis[55];pair<int, int> p[55];bool cmp(pair<int, int> a, pair<int, int> b) {    return a.second < b.second;}void floyd() {    for(int k=0;k<n;k++)    for(int i=0;i<n;i++)    for(int j=0;j<n;j++)        dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);}int solve(){    if(p[n-1].second >= mod)    return 0;    memset(vis, 0, sizeof(vis));    memset(cnt, 0, sizeof(cnt));    vis[0] = 1;    for(int i=1, idx;i<n;i++)    {        idx = p[i].first;        for(int j=0;j<n;j++)            if(vis[j] && dis[0][j] + src[j][idx] == p[i].second)                cnt[idx]++;        vis[idx] = 1;    }    long long ans = 1;    for(int i=1;i<n;i++)        (ans *= cnt[i]) %= mod;    return ans;}int main(){    while(scanf("%d",&n)!=EOF)    {        for(int i=0;i<n;i++)        {            scanf(" %s",&s[i]);            for(int j=0;j<n;j++) {                dis[i][j] = src[i][j] = s[i][j] - '0';                if(dis[i][j] == 0 && i!=j)  dis[i][j] = src[i][j] = mod;            }        }        floyd();        p[0] = make_pair(0, 0);        for(int i=1;i<n;i++)            p[i].first = i, p[i].second = dis[0][i];        sort(p, p+n, cmp);        printf("%d\n", solve());    }}
0 0