HDU6026-Deleting Edges

本篇介绍了一道关于图论的问题,通过构建最短路径的有向无环图,并生成满足特定条件的树形图,进而求解可能的树的数量。使用Dijkstra算法寻找最短路径,并统计每个节点的入度来得出答案。

Deleting Edges

                                                                                Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
                                                                                                                  Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
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 n1. 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 n1 edges.
(2) For every vertice v(0<v<n), the distance between 0 and v on the tree is equal to the length of shortest path from 0 to v 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 i and j, 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+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(1n50), denoting the number of nodes in the graph.
In the following n lines, every line contains a string with n characters. These strings describes the adjacency matrix of the graph. Suppose the j-th number of the i-th line is c(0c9), if c is a positive integer, there is an edge between i and j with length of c, if c=0, then there isn't any edge between i and j.
The input data ensure that the i-th number of the i-th line is always 0, and the j-th number of the i-th line is always equal to the i-th number of the j-th line.
 

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

Sample Input
2 01 10 4 0123 1012 2101 3210
 

Sample Output
1 6
 


题意:有n个点,告诉你两两之间的边,让你去掉一些边,使得0号节点到其他节点都是最短路,问有多少种这样的图

解题思路:最短路,先建一个只包含最短路的有向无环图,每一个点选择任意一条入边即可生成一个树形图,那么树的种类就等于每个点的入度乘积


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <cmath>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long
const int INF=0x3f3f3f3f;
#define mod 1000000007

int n,s[60],nt[5009],e[5009],l[5009],visit[60],dis[60];
LL a[60];
char ch[60][60];

struct node
{
    int id,l;
    friend bool operator <(node a,node b)
    {
        return a.l>b.l;
    }
};

void Dijkstra()
{
    memset(visit,0,sizeof visit);
    memset(dis,INF,sizeof dis);
    priority_queue<node>q;
    node pre,nt1;
    pre.id=0,pre.l=0,a[0]=1;
    dis[0]=0;
    q.push(pre);
    while(!q.empty())
    {
        pre=q.top();
        q.pop();
        visit[pre.id]=1;
        for(int i=s[pre.id];~i;i=nt[i])
        {
            int ee=e[i];
            if(visit[ee]) continue;
            if(dis[ee]>pre.l+l[i])
            {
                a[ee]=1;
                dis[ee]=pre.l+l[i];
                nt1.id=ee;
                nt1.l=dis[ee];
                q.push(nt1);
            }
            else if(dis[ee]==pre.l+l[i])
                a[ee]++;
        }
    }
    LL ans=1;
    for(int i=0;i<n;i++)
    {
        ans*=a[i];
        ans%=mod;
    }
    printf("%lld\n",ans);
}

int main()
{
    while(~scanf("%d",&n))
    {
        int cnt=0;
        memset(s,-1,sizeof s);
        for(int i=0;i<n;i++)
        {
            scanf("%s",ch[i]);
            for(int j=0;j<n;j++)
            {
                if(ch[i][j]!='0')
                    nt[cnt]=s[i],s[i]=cnt,e[cnt]=j,l[cnt++]=ch[i][j]-'0';
            }
        }
        Dijkstra();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值