题目大意:一张无向图上面有Jimmy的家和Jimmy的公司。
Jimmy必须要走满足一下条件的路:如果Jimmy要从A走到B,必须存在一条以B为起点的路径,比从任何一条以A为起点的路径短。
思路:所谓的“必须存在一条以B为起点的路径,比从任何一条以A为起点的路径短。” 也就是说,从A开始的最短路径比从B开始的最短路径短。 因此跑完一边最短路径后,我们对所有d[x] > d[y]的点对建立一条边。
得到的新的图必然是一棵树(想一想,为什么?)
然后跑一边一个很简单的树上dp就可以了。
#include <bits/stdc++.h>
#define CLR(arr) memset(arr,0,sizeof(arr))
using namespace std;
const int maxn = 1020;
typedef long long ll;
struct HeapNode{
int u,d;
bool operator < (const HeapNode& rhs) const
{
return d > rhs.d;
}
};
struct Edge{
int u,v,dist;
};
int ecnt;
int d[maxn];
int p[maxn];
bool done[maxn];
vector<int> G[maxn];
vector<Edge> edge;
void AddEdge(int u, int v, int dist)
{
edge.push_back(Edge{u,v,dist});
G[u].push_back(ecnt++);
}
void dijkstra(int s)
{
CLR(done);
memset(d,0x3f,sizeof(d));
d[s] = 0;
priority_queue<HeapNode> Q;
Q.push(HeapNode{s,0});
while(!Q.empty())
{
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for (int i = 0 ; i < G[u].size() ;++i)
{
Edge &e = edge[G[u][i]];
if(d[e.v] > d[u] + e.dist)
{
d[e.v] = d[u] + e.dist;
p[e.v] = u;
Q.push(HeapNode{e.v,d[e.v]});
}
}
}
}
int F[maxn];
vector<int> tree[maxn];
void init(int n){
CLR(p);
CLR(F);
for (int i = 0 ; i < n ; ++i) G[i].clear();
for (int i = 0 ; i < n ; ++i) tree[i].clear();
edge.clear();
ecnt = 0;
}
int dp(int k)
{
if(k == 0) return 1;
if(F[k] != -1) return F[k];
int& ret = F[k];
ret = 0;
for (int i = 0 ; i < tree[k].size() ; ++i)
{
int v = tree[k][i];
ret += dp(v);
}
return ret;
}
bool vis[maxn];
int main()
{
int n,m;
while(cin >> n )
{
if(n==0) break;
cin >> m;
int a,b,t;
init(n);
for (int i = 0 ; i < m ; ++i)
{
cin >> a >> b >> t;
a--;b--;
AddEdge(a,b,t);
AddEdge(b,a,t);
}
dijkstra(2-1);
CLR(vis);
memset(F,-1,sizeof(F));
for (int u = 0 ; u < n ; ++u)
for (int i = 0 ; i < G[u].size() ; ++i)
{
Edge &e = edge[G[u][i]];
int v = e.v;
if(d[v] > d[u])
tree[u].push_back(v);
}
int ans = 0;
ans = dp(1);
cout << ans << endl;
}
return 0;
}