CF 449B - Jzzhu and Cities(最短路)

题意:给定n个点,m条边的无向图,现在有一些特殊的路线,可以直接从原点1到达某一个点,现在要去掉一些这样的路线,使得去掉这些路线后,从1到各点的最短路距离不变。求去掉的路线的最大值。

思路:开始写了spfa,T掉了,真是不友好……没办法,写dijkstra吧,最开始要处理一下,如果到某一个点的特殊路线有多个,那么选最短的那条,其他直接去掉就好。。。在djikstra的时候,标记一下插入堆中的路线的类型,表示是否由特殊路线直接走到,不是从特殊路线走的优先级较高,对于从堆中取出结点,如果是由特殊路线走到,那么这条路线就是最短的了,所以这条路不能删掉。记一下数就好了。。。。


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<stack>
#include<set>
#include<cmath>
#include<vector>
#define inf 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define eps 1e-9
#define pi acos(-1.0)
using namespace std;
typedef long long ll;
const int maxn=100000+10;
const int maxm=300000+10;
struct Edge
{
    int v,w,next;
    Edge(int v=0,int w=0,int next=0):v(v),w(w),next(next){}
}edges[maxm<<1];
int head[maxn],nEdge;
int direct[maxn];
ll d[maxn];
bool inq[maxn],flag[maxn];
void AddEdges(int u,int v,int w)
{
    edges[++nEdge]=Edge(v,w,head[u]);
    head[u]=nEdge;
    edges[++nEdge]=Edge(u,w,head[v]);
    head[v]=nEdge;
}
struct HeapNode
{
    ll d;
    int u,type;
    HeapNode(ll d=0,int u=0,int type=0):d(d),u(u),type(type){}
    bool operator < (const HeapNode & a) const
    {
        if(a.d==d) return type<a.type;
        return a.d<d;
    }
};
bool vis[maxn];
int dijkstra(int n)
{
    int cnt=0;
    priority_queue<HeapNode>q;
    memset(vis,0,sizeof(vis));
    memset(flag,0,sizeof(flag));
    for(int i=1;i<=n;++i) d[i]=Inf;
    d[1]=0;
    HeapNode hp=HeapNode(0,1,0);
    for(int i=1;i<=n;++i)
        if(direct[i]!=-1) {cnt++;q.push(HeapNode(direct[i],i,-1));d[i]=direct[i];}
    q.push(hp);
    while(!q.empty())
    {
       hp=q.top();q.pop();
       int u=hp.u;
       if(vis[u]) continue;
       vis[u]=true;
       if(hp.type<0) cnt--;
       for(int k=head[u];k!=-1;k=edges[k].next)
       {
           int v=edges[k].v;
           if(d[v]>=d[u]+edges[k].w)
           {
               d[v]=d[u]+edges[k].w;
               q.push(HeapNode(d[v],v,0));
           }
       }
    }
    return cnt;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    memset(head,0xff,sizeof(head));
    memset(direct,0xff,sizeof(direct));
    nEdge=-1;
    int u,v,w;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d%d",&u,&v,&w);
        AddEdges(u,v,w);
    }
    int ans=0;
    for(int i=0;i<k;++i)
    {
        scanf("%d%d",&u,&w);
        if(direct[u]==-1) direct[u]=w;
        else direct[u]=min(direct[u],w),ans++;
    }
    ans+=dijkstra(n);
    printf("%d\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值