HDU 6026 Deleting Edges(读懂题意+spfa)

Deleting Edges

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


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
 

Source

题意:给你一个图,包含n个点若干条带权边,你要随便挑n-1条构成树,且挑出来的边在原图中是到根节点0的距离最小的边。

读题是关键。

先spfa预处理出最短的边。

然后记录每个节点包含的最短的边的数目。

最后乘起来就行了,相当于每个点选一条最短的边,一共就是n-1条。注意long long和mod。

AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int const MAX = 200005;
int const INF = 1 << 30;
const ll mo=1e9+7;
int n, m;

struct EDGE
{
    int u, v;
    int val;
}e[2000010];
struct NODE
{
    int v, w;
    NODE(int vv, int ww)
    {
        v = vv;
        w = ww;
    }
};

vector <NODE> vt[MAX];
int dis[MAX];
bool vis[MAX];

void SPFA(int v0)
{
    memset(vis, false, sizeof(vis));
    for(int i = 1; i <= n; i++)
        dis[i] = INF;
    dis[v0] = 0;
    queue <int> q;
    q.push(v0);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        int sz = vt[u].size();
        for(int i = 0; i < sz; i++)
        {
            int v = vt[u][i].v;
            int w = vt[u][i].w;
            if(dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v] = true;
                }
            }
        }
    }
}
char s[60][60];
ll ans[10010];
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<=n;i++)
        vt[i].clear();
        for(int i=0;i<n;i++) scanf("%s",s[i]);
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            int d=(s[i][j]&15);
            if(d)
            {
                vt[i].push_back(NODE(j, d));
            }
        }
        SPFA(0);
        memset(ans,0,sizeof(ans));
        for(int u=0;u<n;u++)
        {
        int sz = vt[u].size();
        for(int i = 0; i < sz; i++)
        {
            int v = vt[u][i].v;
            int w = vt[u][i].w;
            if(dis[v]==dis[u] + w)
            {
                ans[v]++;
            }
        }
        }
        ll anss=1;
        for(int i=1;i<n;i++)
        {
            //cout<<ans[i]<<endl;
            anss=(anss*ans[i])%mo;
        }
        printf("%lld\n",anss);
    }
    return 0;
}

展开阅读全文

没有更多推荐了,返回首页