Codeforces 144D. Missile Silos【dijkstra】

23 篇文章 0 订阅
9 篇文章 0 订阅

题目大意:

给出一个图,一个源点s,问距离这个源点的最短距离恰好为 l 的点有多少个(这个点可以在边上,可以在节点上)。

做法:

首先用dijkstra算法求出每个节点到s的最短路d[]数组,然后对于每条边w(u,v)来说有下面三种情况是合法的:
1:d[u]<l && l-d[u]<w(u,v) && d[v]+w(u,v)-(l-d[u])>l
2:d[v]<l && l-d[v]<w(u,v) && d[u]+w(u,v)-(l-d[v])>l

3:d[v]<l && d[u]<l && d[u]+d[v]+w(u,v)==2*l

对于上面每种情况,ans++,另外每个d[i]==l 的情况也要ans++;

代码:
#include <iostream>
#include <vector>
#include <cstdio>
#include <queue>
#include <climits>
#include <algorithm>
#define N 100010
const int INF=INT_MAX;
using namespace std;
struct edge
{
    int from,to,c;
    edge(int a,int b)
    {
        to=a,c=b;
    }
    edge()
    {
        from=0,to=0,c=0;
    }
};
edge e[N];
typedef pair<int,int> p;
int V;
vector <edge> G[N*2];
int d[N];
void dijkstra(int s)
{
    priority_queue<p,vector<p>,greater<p> > que;
    fill(d+1,d+V+1,INF);
    d[s]=0;
    que.push(p(0,s));
    while(!que.empty())
    {
        p pp=que.top();que.pop();
        int v=pp.second;
        if(d[v]<pp.first) continue;
        for(int i=0;i<G[v].size();i++){
            edge e=G[v][i];
            if(d[e.to]>d[v]+e.c)
            {
                d[e.to]=d[v]+e.c;
                que.push(p(d[e.to],e.to));
            }
        }
    }
}
int main()
{
    int m,l,s;
    int ans=0;
    scanf("%d%d%d",&V,&m,&s);
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        G[a].push_back(edge(b,c));
        G[b].push_back(edge(a,c));
        e[i].from=a,e[i].to=b,e[i].c=c;
    }
    scanf("%d",&l);
    dijkstra(s);
    for(int i=0;i<m;i++)
    {
        int u=e[i].from,v=e[i].to,cost=e[i].c;
        if(d[u]<l && l-d[u]<cost && d[v]+cost-(l-d[u])>l) ans++;
        if(d[v]<l && l-d[v]<cost && d[u]+cost-(l-d[v])>l) ans++;
        if(d[u]<l && d[v]<l && d[u]+d[v]+cost==2*l) ans++;
    }
    for(int i=1;i<=V;i++)
        if(d[i]==l) ans++;
    cout<<ans<<endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值