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

你可能感兴趣的:(codeforces)