HDU - 6026 Deleting Edges (最短路Dijkstra+思维)

Deleting Edges 

Little Q is crazy about graph theory, and now he creates a game about graphs and trees. 
There is a bi-directional graph with nn nodes, labeled from 0 to n−1n−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−1n−1 edges. 
(2) For every vertice v(0<v<n)v(0<v<n), the distance between 0 and vv on the tree is equal to the length of shortest path from 0 to vv in the original graph. 
Little Q wonders the number of ways to delete edges to get such a satisfied graph. If there exists an edge between two nodes ii and jj, while in another graph there isn't such edge, then we regard the two graphs different. 
Since the answer may be very large, please print the answer modulo 109+7109+7.

Input

The input contains several test cases, no more than 10 test cases. 
In each test case, the first line contains an integer n(1≤n≤50)n(1≤n≤50), denoting the number of nodes in the graph. 
In the following nn lines, every line contains a string with nn characters. These strings describes the adjacency matrix of the graph. Suppose the jj-th number of the ii-th line is c(0≤c≤9)c(0≤c≤9), if cc is a positive integer, there is an edge between ii and jj with length of cc, if c=0c=0, then there isn't any edge between ii and jj. 
The input data ensure that the ii-th number of the ii-th line is always 0, and the jj-th number of the ii-th line is always equal to the ii-th number of the jj-th line.

Output

For each test case, print a single line containing a single integer, denoting the answer modulo 109+7109+7.

Sample Input

2
01
10
4
0123
1012
2101
3210

Sample Output

1
6

题目大意:给一个n个节点的图,现在要删边,把图删成一棵n-1条边的树,使所有节点到0点的距离为原图上此节点到0的最短距离,问有几种删法

思路:问有几种删法实际上就是问能构成几种满足条件的树,要使节点到0的距离为最短,那么肯定要用最短路算法求出最短距离,对于边(u,v),若dis[u]+len[u][v]==dis[v],则c[v]++;   即从v点出发的可选边增加一条。最后每个节点都选出一条出发的可选边即可组成一颗目标树,因此只需要乘起来累计答案即可

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int mod=1e9+7;
const int N=60;
int e[N][N],dis[N],vis[N],c[N];
int n;
void dij()
{
    for(int i=1;i<=n;i++)
    {
        dis[i]=inf;
        vis[i]=0;
        c[i]=0;
    }
    dis[1]=0;
    for(int i=1;i<=n;i++)
    {
        int minn=inf;
        int k;
        for(int j=1;j<=n;j++)
            if(!vis[j]&&dis[j]<minn)
        {
            minn=dis[j];
            k=j;
        }
        vis[k]=1;
        for(int j=1;j<=n;j++)
        {
            if(!e[k][j]) continue;
            if(!vis[j]&&dis[j]>dis[k]+e[k][j])
            {
                c[j]=0;
                dis[j]=dis[k]+e[k][j];
            }
            if(dis[j]==dis[k]+e[k][j])
                c[j]++;
        }
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        char s[60];
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s);
            for(int j=1;j<=n;j++)
                e[i][j]=s[j-1]-'0';
        }
        dij();
        ll ans=1;
        for(int i=2;i<=n;i++)
        //printf("%d\n",c[i]);
            ans=(ans*(ll)c[i])%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值