1. 程式人生 > >Hdu 6026 Deleting Edges【思維+最短路】

Hdu 6026 Deleting Edges【思維+最短路】

Deleting Edges

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


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 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 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 10
9
+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到任意點v的距離都是原圖的最短路的距離。

思路:

首先我們預處理出從點0到其他各個點的最短路的距離dist【i】.

那麼對應如果有dist【i】+w==dist【j】,那麼從i到j這條邊就可以作為構成生成樹的一條邊。

那麼我們將所有可以未做生成樹的邊的個數處理出來,那麼對應在每個點上邊取一條邊出來作為答案即可。

那麼累成結果就行了。

Ac程式碼:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
char a[55][55];
int dist[55];
int vis[55];
int ans[55];
int n;
void SPFA()
{
    memset(vis,0,sizeof(vis));
    queue<int >s;
    for(int i=0;i<n;i++)dist[i]=0x3f3f3f3f;
    dist[0]=0;
    s.push(0);
    while(!s.empty())
    {
        int u=s.front();
        vis[u]=0;
        s.pop();
        for(int i=0;i<n;i++)
        {
            if(a[u][i]!='0')
            {
                int v=i;
                int w=a[u][i]-'0';
                if(dist[v]>dist[u]+w)
                {
                    dist[v]=dist[u]+w;
                    if(vis[v]==0)
                    {
                        vis[v]=1;
                        s.push(v);
                    }
                }
            }
        }
    }
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)scanf("%s",a[i]);
        SPFA();
        memset(ans,0,sizeof(ans));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(a[i][j]=='0')continue;
                else
                {
                    int w=a[i][j]-'0';
                    if(dist[i]+w==dist[j])
                    {
                        ans[j]++;
                    }
                }
            }
        }
        __int64 output=1;
        for(int i=1;i<n;i++)
        {
            output*=(__int64)ans[i];
            output%=1000000000+7;
        }
        printf("%I64d\n",output);
    }
}