Fork me on GitHub

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\n",cnt);
    }
    return 0;
}
View Code
posted @ 2014-07-20 10:21  whatbeg  阅读(353)  评论(0编辑  收藏  举报