/**//* 参考watashi Orz 题意:先求一个有向图从0到其他点的最短路中,询问某些点在这些最短路出现的次数 先dij 或 spfa 求最短路 然后dp,用乘法原理 “可以分别求出0到节点v的最短路数和从节点v出发的最短路数,而经过包含v的最短路数就是这二者的乘积” 最后结果是保留最后10位,中间的乘法用long long也会超 “用布斯(Booth)乘法” 高位的不用乘,方正 % MOD = 0
我是建正图反图两次dfs的 */ #include<cstdio> #include<cstring> #include<algorithm> #include<queue>
using namespace std;
const int MAXN = 10086; const long long MOD = 10000000000; const int INF = 1000000000;
struct Node { int v,w; Node *next; };
Node *E[MAXN],*_E[MAXN],*pE,nodes[MAXN*10]; long long s[MAXN] , t[MAXN]; long long dist[MAXN]; bool vi[MAXN],in[MAXN];
void init(int N) { pE = nodes; for(int i=0;i<N;i++)E[i] = _E[i] = NULL; }
void addEdge(int u,int v,int w) { pE->v = v; pE->w =w; pE->next = E[u]; E[u] = pE++;
pE->v = u; pE->w =w; pE->next = _E[v]; _E[v] = pE++; }
long long mul(long long a,long long b) { long long la = a % 100000; long long lb = b % 100000; return ( (a / 100000 * lb + b / 100000 * la) * 100000 + la * lb) % MOD; // a / 100000 * b / 100000 这个不用了因为%MOD后还是为0 }
long long add(long long a,long long b) { a += b; if(a >= MOD) a %= MOD; return a; }
void spfa(int N) { for(int i=1;i<N;i++) { dist[i] = INF; in[i] = false; } dist[0] = 0; in[0] = true; queue<int>Q; Q.push(0); while(!Q.empty()) { int u = Q.front();Q.pop(); in[u] = false; for( Node *it = E[u]; it; it = it->next ) { int v = it->v, w = it->w; if( dist[v] > dist[u] + w ) { dist[v] = dist[u] + w; if(!in[v]) { in[v] = true; Q.push(v); } } } } }
void forward(int u)//calculate the success Edge t[] { for( Node *it = E[u]; it; it = it->next) { int v = it->v, w = it->w; if(dist[v] == dist[u] + w) { if(!vi[v])forward(v); t[u] = add(t[u],t[v]); } } vi[u] = true; }
void backward(int u)//calculate the pre Edge s[] { for( Node *it = _E[u]; it; it = it->next) { int v = it->v, w = it->w; if(dist[u] == dist[v] + w) { if(!vi[v])backward(v); s[u] = add(s[u] , s[v]); } } vi[u] = true; }
int main() { #ifdef ONLINE_JUDGE #else freopen("in","r",stdin); #endif
int N,Q,M; while( ~scanf("%d%d%d",&N,&M,&Q) ) { init(N); int u,v,w; for(int i=0;i<M;i++) { scanf("%d%d%d",&u,&v,&w); addEdge(u,v,w); } spfa(N); for(int i=0; i<N; i++) { s[i] = 0; t[i] = 1; } s[0] = 1; memset(vi,0,sizeof(vi)); forward(0); memset(vi,0,sizeof(vi)); for(int i=0;i<N;i++) { if(!vi[i])backward(i); } for( int i = 0; i<Q; i++) { scanf("%d",&u); printf("%010lld\n",mul(s[u],t[u])); } } return 0; }
|
|
常用链接
随笔分类
Links
搜索
最新评论
|
|