转载注明出处 http://blog.youkuaiyun.com/moedane
传送门 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3408
题意
给出一个有向图,从点0出发,询问经过每个点的最短路的条数。
思路
经过一个点的最短路的数目 = 以该点为结尾的最短路的数目 * 从该点出发的最短路的数目。(这是重点)
spfa一次记录最短路的图。
然后正向dfs一次得到以每个点出发所能达到的最短路的数目。
反向dfs一次得到以每个店做结尾的最短路的数目,这里需要反向建一次图。
做乘法的时候要避免过程溢出。
这道题做到我心力交瘁,莫名wa=。=
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <stack>
#include <fstream>
#include <map>
#include <set>
#define bug puts("here");
using namespace std;
typedef long long ll;
const int maxn = 10100;
const ll mod = 1e10;
const int inf = 0x3f3f3f3f;
const double PI = atan(1.0) * 4.0;
const double eps = 1e-8;
ll dis[maxn];
int head[maxn],edge[maxn*10],nxt[maxn*10], w[maxn*10];
vector<int> pos[maxn], neg[maxn];
ll ed[maxn],st[maxn];
int in[maxn];
bool vis[maxn];
int n,m,q;
int cnt;
void init()
{
cnt = 0;
memset(head,-1,sizeof head);
memset(dis,0x3f,sizeof dis);
dis[0] = 0;
for(int i=0;i<n;i++) pos[i].clear(), neg[i].clear();
memset(ed,0,sizeof ed);
memset(st,0,sizeof st);
memset(in,0,sizeof in);
}
void spfa()
{
queue<int> Q;
memset(vis, false,sizeof vis);
Q.push(0);
while(!Q.empty())
{
int u = Q.front(); Q.pop();
vis[u] = false;
for(int i=head[u]; i!=-1 ; i=nxt[i])
{
int v = edge[i];
if(dis[v] == dis[u] + w[i]){
neg[v].push_back(u);
}
if(dis[v] > dis[u] + w[i]){
dis[v] = dis[u] + w[i];
neg[v].clear();
neg[v].push_back(u);
if(!vis[v])
vis[v] = true, Q.push(v);
}
}
}
}
void getPos(){
for(int i=0;i<n;i++){
for(int j=0;j<neg[i].size();j++){
int u = neg[i][j];
in[u] ++;
pos[u].push_back(i);
}
}
}
void addEdge(int u,int v,int d){
edge[cnt] = v;
w[cnt] = d;
nxt[cnt] = head[u];
head[u] = cnt ++;
}
ll dfsST(int u){
if(st[u] > 0) return st[u];
ll sum = 1;
for(int i=0;i<pos[u].size() ;i++){
int v = pos[u][i];
sum = (sum + dfsST(v)) % mod;
}
return st[u] = sum;
}
ll dfsED(int u){
if(u == 0) return ed[u] = 1;
if(ed[u] > 0) return ed[u];
ll sum = 0;
for(int i=0;i<neg[u].size() ; i ++) {
int v = neg[u][i];
sum = (sum + dfsED(v)) % mod;
}
return ed[u] = sum;
}
ll mul(ll a,ll b){
ll ret = 0;
a %= mod;
while(b){
if(b&1){
ret = (ret + a) % mod;
}
a = (a << 1) % mod;
b >>= 1;
}
return ret;
}
int main(){
while(~scanf("%d%d%d",&n,&m,&q)){
init();
int i;
for(i=0;i<m;i++){
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
addEdge(u,v,d);
}
spfa();
getPos();
dfsST(0);
for(i=0;i<n;i++) if(in[i] == 0) dfsED(i);
while(q --){
int u;
scanf("%d",&u);
printf("%010lld\n",mul(st[u], ed[u]));
}
}
}