div2的D题~~要求距离图上一个点的所有距离为 l 的位置,简单题~~我的方法是先用spfa求出每个点到源点 s 的距离,这样的话每一条边上的点到 s 的最小距离也能推导出来~~然后枚举,枚举每一个点和每一条边 ,枚举边的时候要特别小心,很容易漏掉或者重复计算,这种题目细节是关键。。。
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<cstring>
#include<set>
#include<iomanip>
#include<cassert>
using namespace std;
const int inf = 0x3f3f3f3f;
const double oo = 10e9;
const double eps = 10e-7;
const int maxn=101111;
struct zz
{
int from;
int to;
int cost;
int id;
}zx,tz;
int n,m,s,l;
vector<zz>g[maxn];
bool inq[maxn];
queue<int>q;
int way[maxn];
bool vis[maxn];
void spfa()
{
while(!q.empty())
{
q.pop();
}
for(int i=1;i<=n;i++)
{
way[i]=inf;
}
way[s]=0;
memset(inq,false,sizeof(inq));
q.push(s);
inq[s]=true;
int now,to,cos;
while(!q.empty())
{
now = q.front();
q.pop();
for(int i=0;i<g[now].size();i++)
{
to = g[now][i].to;
cos = way[now] + g[now][i].cost;
if(cos < way[to])
{
way[to]=cos;
if ( !inq[to] )
{
q.push(to);
inq[to]=true;
}
}
}
inq[now]=false;
}
return ;
}
int bfs()
{
spfa();
memset(vis,false,sizeof(vis));
int ans=0;
int to;
int cost;
for(int i=1;i<=n;i++)
{
if(way[i] == l)
{
ans++;
}
for(int j=0;j<g[i].size(); j++ )
{
to = g[i][j].to;
cost = g[i][j].cost;
if ( vis [ g[i][j].id ] )
{
continue;
}
vis[ g[i][j].id ] = true;
if ( way[to]>=l && way[i] >= l )
{
continue;
}
else if( (way[to] > l && way[i] < l) || (way[i] > l && way[to] < l) )
{
ans++;
}
else if(cost + way[i] + way[to] == 2*l )
{
if(l - way[to] > 0 && l - way[to] < cost)
ans++;
}
else if( cost + way[i] + way[to] > 2*l )
{
if( l - way[to] > 0 )
ans++;
if( l - way[i] > 0)
ans++;
}
}
}
return ans;
}
int main()
{
while(cin>>n>>m>>s)
{
for(int i=1;i<=n;i++)
{
g[i].clear();
}
for(int i=1;i<=m;i++)
{
cin>>zx.from>>zx.to>>zx.cost;
zx.id=i;
g[zx.from].push_back(zx);
swap(zx.from,zx.to);
g[zx.from].push_back(zx);
}
cin>>l;
cout<<bfs()<<endl;
}
return 0;
}