码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #257 div.2 D or 450D Jzzhu and Cities【最短路】

时间:2015-03-04 06:17:49      阅读:184      评论:0      收藏:0      [点我收藏+]

标签:codeforces   最短路   图论   

Codeforces Round #257 div.2 D or 450D Jzzhu and Cities【最短路】

  • 题目链接点击打开

  • 题目大意
    在一个国家中有n个城市(城市编号1~n),m条公路和k条铁路,编号为1的城市为首都,为了节约,不需要的铁路需要关闭,问在保证首都到其余所有城市的最短路不变的条件下,最多有多少条铁路是不需要的。

  • 解法
    这个题比较麻烦,保证首都到其余城市的最短路不变,要求出最多有多少条铁路是不需要的,那肯定是从最短路的代码上下手了,我们首先考虑dijkstra算法,假设此时我们处理的图没有重边。

    • 由于要使不需要的铁路最多,那么我们的用来做最短路的路径上的边应该尽可能保证是公路,也就是说,当从首都到某个城市的最短路有多条的时候,我们应该选择铁路最少的一条。那么我们在算法中的“松弛”操作中应该加上这个判断。
    • 我们可以利用一个path[]数组记录哪两个点之间的边是最短路径上的边,记录下这个,我们就可以在遍历过程中方便的判断哪些铁路是不需要的,哪些铁路是在最短路径上的,以此来得到答案。其中path[v]=u,表示(u,v)这条边在最短路径上。由于没有重边,所以这样是能够确定一条边的。
    • 由于前面的结论是在图中没有重边的基础上得出的,然而题目却会给出有重边的数据,于是我们应该先去掉原有数据中的重边。去除重边的时候,要留下两个城市之间边权值最小的一条,这一条尽可能是公路,去除重边的同时,被去除掉的铁路也应该记入答案中。

    让我百思不得其解的是,我写完此题submit之后居然给我返回了一个MLE!让我想半天想不通,CF服务器内存限制一直是256MB,很少出现这种情况,也不可能是数组太大的缘故,我想了很久,突然想到很有可能是dijkstra算法中的优先队列存的数据太多导致的内存超出限制,于是赶紧加了一条限制。果然就过了。

      

    //MLE code(松弛部分): 
      if(d[v]>d[u]+w || (d[v]==d[u]+w && !is))
    {
    path[v]=u;
    d[v]=d[u]+w;
    que.push(PII(d[v],v));
    }
    //AC code(松弛部分):
    if(d[v]>d[u]+w || (d[v]==d[u]+w && !is && trainofpath[v]))
    {
    trainofpath[v]=is;
    path[v]=u;
    d[v]=d[u]+w;
    que.push(PII(d[v],v));
    }
      

      这里采用了一个布尔数组trainofpath[v]记录到v点的这条边是不是铁路。如果这条路原本是铁路,现在更新的是公路,才进行更新;想上一份MLE的代码如果只要当前更新的是公路就进行操作的话,一些变态的数据会使得压入优先队列中的数据过多,导致MLE。
      完整代码如下:
      

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 200010
using namespace std;
const long long INF=0x7fffffffffffffffL;
struct edge
{
    long long u,v,w,nxt;
    bool istrain;
    bool operator< (const edge& o) const
    {
        return u<o.u||(u==o.u && v<o.v)
        ||(u==o.u && v==o.v && w<o.w)
        ||(u==o.u && v==o.v && w==o.w && istrain<o.istrain);
    }
}e1[N*4],e[N*3];
long long last[N];
typedef pair<long long,long long> PII;
long long V;
long long d[N];
long long path[N];
bool trainofpath[N];
priority_queue<PII,vector<PII>,greater<PII> > que;
void dijkstra(long long s)
{
    //memset(d,0x3f,sizeof(d));
    fill(d+1,d+V+1,INF);
    d[s]=0;
    que.push(PII(0,s));
    while(!que.empty())
    {
        PII pp=que.top();que.pop();
        long long u=pp.second;
        if(d[u]<pp.first) continue;
        for(long long i=last[u];i!=-1;i=e[i].nxt){
            long long v=e[i].v,w=e[i].w;
            bool is=e[i].istrain;
            if(d[v]>d[u]+w || (d[v]==d[u]+w && !is && trainofpath[v]))
            {
                trainofpath[v]=is;
                path[v]=u;
                d[v]=d[u]+w;
                que.push(PII(d[v],v));
            }
        }
    }
}
int main()
{
    long long n,m,k;
    scanf("%I64d%I64d%I64d",&n,&m,&k);
    V=n;
    long long ans=0;
    memset(last,-1,sizeof(last));
    for(int i=0;i<=n;i++)
    {
        trainofpath[i]=true;
    }
    for(long long i=0;i<m;i++)
    {
        long long u,v,w;
        scanf("%I64d%I64d%I64d",&u,&v,&w);
        if(u>v) swap(u,v);
        e1[i].u=u,e1[i].v=v,e1[i].w=w,e1[i].istrain=false;
    }
    for(long long i=0;i<k;i++)
    {
        long long v,w;
        scanf("%I64d%I64d",&v,&w);
        e1[i+m].u=1,e1[i+m].v=v,e1[i+m].w=w,e1[i+m].istrain=true;
    }
    sort(e1,e1+m+k);
    long long edge1Num=1;
    for(long long i=1;i<m+k;i++)
    {
        if(e1[i].u==e1[i-1].u && e1[i].v==e1[i-1].v)
        {
            if(e1[i].istrain) ans++;
            continue;
        }
        e1[edge1Num++]=e1[i];
    }

    long long edgeNum=0;
    for(long long i=0;i<edge1Num;i++)
    {
        long long u=e1[i].u,v=e1[i].v,w=e1[i].w;
        bool is=e1[i].istrain;
        e[edgeNum].u=u,e[edgeNum].v=v,e[edgeNum].w=w,e[edgeNum].istrain=is,e[edgeNum].nxt=last[u],last[u]=edgeNum++;
        e[edgeNum].v=u,e[edgeNum].u=v,e[edgeNum].w=w,e[edgeNum].istrain=is,e[edgeNum].nxt=last[v],last[v]=edgeNum++;
    }

    dijkstra(1);

    for(long long i=0;i<edgeNum;i+=2)
    {
        long long u=e[i].u,v=e[i].v;
        bool is=e[i].istrain;
        if(!is) continue;
        if(path[v]==u || path[u]==v) continue;
        ans++;
    }
    cout<<ans<<endl;
    return 0;
}

(这次试了一下新功能Markdown编辑器^_^不怎么会用,看起来比较丑,不过代码显示好像没有以前的漂亮…..可能还需要学习一下新的姿势,嘿嘿)

Codeforces Round #257 div.2 D or 450D Jzzhu and Cities【最短路】

标签:codeforces   最短路   图论   

原文地址:http://blog.csdn.net/u013912596/article/details/44050289

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!