HDU 6026(最短路)
题面:
Total Submission(s): 1154 Accepted Submission(s): 407
Deleting Edges
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1154 Accepted Submission(s): 407
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 n−1 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.
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<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(1≤n≤50), 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(0≤c≤9), 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.
In each test case, the first line contains an integer n(1≤n≤50), 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(0≤c≤9), 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
题目描述:给你一张图,每次你都可以删除一条边,要求删除的边之后,整个图的最短路不发生改变。问一共会有多少种图的可能性。
题目分析:这是一道最短路的变形思维题。拿到题目时,我们不能看到题目中要求我们删边而被删边限制住了思维。首先我们得思考,如果删除掉一条边,而使整张图的最短路不变,那么可以认为,这条路径是对整张图的最短路没有贡献的。再进一步思考,如果一条路径对最短路没有贡献,那么可以看作在跑最短路的过程的松弛操作中,d[to]==cost+d[pre]; 即此时的这条路径跟原有最短路径重合,因此这条边即使可以删去的边。因此我们在跑最短路的过程中,不断寻找满足路径等于原有最短路的边,并使这条路径的子结点的入度加一(表示存在这么一条可以删的边)。最后我们只需要枚举所有的点,将所有可以删除的边累乘起来即是我们所要求的答案。
#include <bits/stdc++.h>
#define maxn 55
#define maxm 5008
using namespace std;
typedef pair<int,int>PLL;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
struct edge{
int next,to,cost;
}q[maxm];
int head[maxm],cnt,d[maxm];
int n;
ll inde[maxm];
bool vis[maxm];
char str[maxn][maxn];
void add_edge(int from,int to,int cost){
q[cnt].cost=cost;
q[cnt].to=to;
q[cnt].next=head[from];
head[from]=cnt++;
}
void dijk(){
priority_queue<PLL,vector<PLL>,greater<PLL> >que;
memset(vis,0,sizeof(vis));
memset(d,INF,sizeof(d));
d[0]=0;
que.push(PLL(0,0));
inde[0]=1;
while(!que.empty()){
PLL p=que.top();
que.pop();
int x=p.second;
vis[x]=1;
for(int i=head[x];i!=-1;i=q[i].next){
edge e=q[i];
if(vis[e.to]) continue;
if(d[e.to]>p.first+e.cost){
inde[e.to]=1;
d[e.to]=p.first+e.cost;
que.push(PLL(d[e.to],e.to));
}
else if(d[e.to]==p.first+e.cost){
inde[e.to]++;
}
}
}
}
void init(){
memset(head,-1,sizeof(head));
cnt=0;
}
int main()
{
while(cin>>n){
init();
for(int i=0;i<n;i++){
scanf("%s",str[i]);
for(int j=0;j<n;j++){
if(str[i][j]!='0'){
add_edge(i,j,str[i][j]-'0');
}
}
}
dijk();
ll ans=1;
for(int i=0;i<n;i++){
ans*=inde[i];
ans%=mod;
}
cout<<ans<<endl;
}
return 0;
}