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

来源:互联网 发布:js push unshift 编辑:程序博客网 时间:2024/05/22 05:12

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 200010using 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编辑器^_^不怎么会用,看起来比较丑,不过代码显示好像没有以前的漂亮…..可能还需要学习一下新的姿势,嘿嘿)

0 0
原创粉丝点击