• Codeforces Round #257(Div.2) D Jzzhu and Cities --SPFA


    题意:n个城市,中间有m条道路(双向),再给出k条铁路,铁路直接从点1到点v,现在要拆掉一些铁路,在保证不影响每个点的最短距离(距离1)不变的情况下,问最多能删除多少条铁路

    分析:先求一次最短路,铁路的权值大于该点最短距离的显然可以删去,否则将该条边加入图中,再求最短路,记录每个点的前一个点,然后又枚举铁路,已经删去的就不用处理了,如果铁路权值大于该点最短距离又可以删去,权值相等时,该点的前一个点如果不为1,则这个点可以由其他路到达,这条铁路又可以删去。

    由于本题中边比较多,最多可以有8x10^5条,所以用邻接链表会超时,最好用vector来存储边。

    Time:296 ms Memory:30968 KB

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #define lll __int64
    using namespace std;
    #define N 100006
    
    struct Edge
    {
        int v;
        lll w;
        Edge(int _v,lll _w)
        {
            v = _v;
            w = _w;
        }
        Edge(){}
    };
    
    struct Train
    {
        int v;
        lll w;
    }T[N];
    
    vector<Edge> G[N];
    lll dis[N];
    int n,m;
    int head[N],tot,pre[N];
    int cut[N],vis[N];
    queue<int> que;
    
    void SPFA(int s)
    {
        while(!que.empty())
            que.pop();
        memset(vis,0,sizeof(vis));
        vis[s] = 1;
        que.push(s);
        for(int i=0;i<=n;i++)
            dis[i] = 1000000000000000LL;
        dis[s] = 0;
        while(!que.empty())
        {
            int u = que.front();
            que.pop();
            vis[u] = 0;
            for(int i=0;i<G[u].size();i++)
            {
                int v = G[u][i].v;
                lll w = G[u][i].w;
                if(dis[v] > dis[u] + w)
                {
                    dis[v] = dis[u] + w;
                    if(!vis[v])
                    {
                        vis[v] = 1;
                        que.push(v);
                    }
                }
            }
        }
    }
    
    void SPFA2()
    {
        while(!que.empty())
        {
            int u = que.front();
            que.pop();
            vis[u] = 0;
            for(int i=0;i<G[u].size();i++)
            {
                int v = G[u][i].v;
                lll w = G[u][i].w;
                if(dis[v] > dis[u] + w)
                {
                    dis[v] = dis[u] + w;
                    pre[v] = u;
                    if(!vis[v])
                    {
                        que.push(v);
                        vis[v] = 1;
                    }
                }
                else if(dis[v] == dis[u] + w && pre[v] < u)
                    pre[v] = u;
            }
        }
    }
    
    int main()
    {
        int i,j,k;
        int u,v,y;
        lll w;
        while(scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
            tot = 0;
            for(i=0;i<=n;i++)
                G[i].clear();
            memset(head,-1,sizeof(head));
            memset(cut,0,sizeof(cut));
            memset(pre,-1,sizeof(pre));
            for(i=0;i<m;i++)
            {
                scanf("%d%d%I64d",&u,&v,&w);
                G[u].push_back(Edge(v,w));
                G[v].push_back(Edge(u,w));
            }
            for(i=0;i<k;i++)
            {
                scanf("%d%I64d",&y,&w);
                T[i].v = y;
                T[i].w = w;
            }
            SPFA(1);
            int cnt = 0;
            for(i=0;i<k;i++)
            {
                int v = T[i].v;
                lll w = T[i].w;
                if(dis[v] <= w)
                {
                    cut[i] = 1;
                    cnt++;
                }
                else
                {
                    G[1].push_back(Edge(v,w));
                    G[v].push_back(Edge(1,w));
                    pre[v] = 1;
                    dis[v] = w;
                    que.push(v);
                    vis[v] = 1;
                }
            }
            SPFA2();
            for(i=0;i<k;i++)
            {
                if(cut[i])
                    continue;
                int v = T[i].v;
                lll w = T[i].w;
                if((dis[v] == w && pre[v] != 1) || dis[v] < w)
                    cnt++;
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    java事件处理机制(自定义事件)
    EL表达式 (详解)
    Java编程思想(四) —— 复用类
    优秀辅助网站使用记录
    快速部署tomcat项目的Shell脚本
    数据库SQL优化大总结
    常用排序算法及应用背景
    Java面试通关秘籍汇总集
    Java堆、栈和常量池以及相关String详解
    常用加密算法概述
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3855921.html
Copyright © 2020-2023  润新知