Brief Description:
给出一个有向图,节点编号0->n-1,现在求0到其他点的最短路,考虑所有最短路的路径,求某节点出现多少次。
Analysis:
此题还是很容易yy的。
首先求0到其他点的最短路,然后根据得到的最短路的值求出一个DAG,保证DAG里所有从0开始的路径都是最短路.
设dp1[u]是从u开始到其他点的最短路的个数,dp2[u]是其他点到u的最短路的个数。
求u出现多少次就是 dp1[u]*dp2[u]
求dp1[u],dp2[u]可以用DAG上的dp解决,为了方便处理引入一个终止节点,所有点都连向这个终止节点,至于为什么,自己脑补:)
宏观上这么做算法是对的,但是此题trick颇多。
1.答案要求保留后10位,所以要%(10^10),但是两个10位数相乘会超longlong,所以得用布斯乘法,具体见代码
2.图可以有自环,可以有重边,因为这个错了无数次!!!
代码如下:
// ZOJ3408
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
typedef long long LL;
const LL mod = 10000000000LL;
const int maxn = 10006;
struct node
{
int id;
int w;
node() {}
node(int _id,int _w)
{
id = _id;
w = _w;
}
bool operator<(const node &p)const
{
return w > p.w; // basic coding
}
};
int n,m,q;
int dis[maxn];
vector<node>V[maxn];
bool vis[maxn];
priority_queue<node>pq; //йтве╥ехКdijжп
void dij()
{
int i;
int Size = (int)V[1].size();
while(!pq.empty()) pq.pop(); // basic coding
memset(dis,0x3f,sizeof(dis));
dis[1] = 0;
memset(vis,0,sizeof(vis));
vis[1] = 1;
for(i=0; i<Size; i++)
{
pq.push(node(V[1][i].id,V[1][i].w));
if(V[1][i].id != 1 && V[1][i].w < dis[V[1][i].id])
dis[V[1][i].id] = V[1][i].w;
}
node T;
while(!pq.empty()) // basic doding..
{
T = pq.top();
pq.pop();
if(!vis[T.id])
{
vis[T.id] = 1;
Size = (int)V[T.id].size();
for(i=0; i<Size; i++)
{
int id = V[T.id][i].id;
int w = V[T.id][i].w;
if(!vis[id] && dis[T.id]+w<dis[id])
{
dis[id] = dis[T.id] + w;
pq.push(node(id,dis[id]));
}
}
}
}
}
vector<node>G[2][maxn];
LL dp1[maxn],dp2[maxn];
void getG()
{
for(int u=1; u<=n; u++) // get every edge
{
int S = (int)V[u].size();
for(int i=0; i<S; i++)
{
int v = V[u][i].id;
int w = V[u][i].w;
if(dis[u]+w==dis[v]) // Good!
{
G[0][u].push_back(node(v,w));
G[1][v].push_back(node(u,w));
}
}
}
for(int i=1; i<=n; i++)
{
G[1][n+1].push_back(node(i,0));
G[0][i].push_back(node(n+1,0));
}
}
LL DFS(int u,LL *dp,int pos)
{
if(vis[u]) return dp[u];
int S = (int)G[pos][u].size();
if(S == 0)
{
dp[u] = 1;
vis[u] = 1;
return 1;
}
for(int i=0; i<S; i++)
{
int v = G[pos][u][i].id;
LL tmp = DFS(v,dp,pos);
dp[u] = ( dp[u] + tmp ) % mod;
}
vis[u] = 1;
return dp[u];
}
LL Mul(LL lhs,LL rhs) // basic coding
{
LL lhs2=lhs%100000;
LL rhs2=rhs%100000;
return ((lhs/100000*rhs2+rhs/100000*lhs2)*100000+lhs2*rhs2)%mod;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&q) == 3)
{
for(int i=0; i<=n+1; i++)
{
G[0][i].clear();
V[i].clear();
G[1][i].clear();
dp1[i] = dp2[i] = vis[i] = 0;
}
// G[1][n+1].clear();
for(int i=1; i<=m; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
u++;
v++;
V[u].push_back(node(v,w));
}
dij();
getG();
memset(vis,0,sizeof(vis));
DFS(1,dp1,0);
memset(vis,0,sizeof(vis));
DFS(n+1,dp2,1);
LL an;
while(q--)
{
int u;
scanf("%d",&u);
u++;
if(u > n)
{
printf("%010lld\n",0);
continue;
}
an = Mul(dp1[u],dp2[u]);
printf("%010lld\n",an);
}
}
return 0;
}