• Codeforces 449B_Jzzhu and Cities


    给一个无向图,外加一些特殊的连接原点的无向边。在不改变原点与所有点的最短路的情况下,最多可以删除多少条特殊边?

    首先我们把所有的边夹杂在一起。spfa跑出与所有点的最短路。

    接下来我们通过一次bfs来判断哪些特殊的边是可以删除的。这里面的原理跟迪杰斯特拉算法差不多。

    首先把原点加入队列,所有的特殊边按照长度排序,然后一直沿着非特殊边和最短的路径增广,把满足最短路条件的点都拉到队列里面来,直到队列元素为空,然后判断特殊边的最短的那一条边是否关键边,是的话就把它所连接的那个点拉到队列里面来。程序一直进行直到队列元素空且所有的特殊边都进行过判断为止。

    召唤代码君:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 1111111
    typedef long long ll;
    using namespace std;
    
    struct EG{
        ll v,w;
    }E[500100];
    
    ll inf=~0U>>2;
    ll to[maxn],next[maxn],c[maxn],first[maxn],edge;
    ll U[maxn],V[maxn],W[maxn],d[maxn];
    ll Q[maxn],bot,top;
    bool iq[maxn];
    ll n,m,k,tk,ans=0;
    
    bool cmp(EG e1,EG e2)
    {
        return e1.w<e2.w;
    }
    
    void addedge(ll uu,ll vv,ll ww)
    {
        edge++;
        to[edge]=vv,c[edge]=ww,next[edge]=first[uu],first[uu]=edge;
        edge++;
        to[edge]=uu,c[edge]=ww,next[edge]=first[vv],first[vv]=edge;
    }
    
    void _init()
    {
        scanf("%I64d%I64d%I64d",&n,&m,&k);
        for (ll i=1; i<=n; i++) first[i]=-1,d[i]=inf,iq[i]=false;
        edge=-1;
        for (ll i=1; i<=m; i++) scanf("%I64d%I64d%I64d",&U[i],&V[i],&W[i]),addedge(U[i],V[i],W[i]);
        tk=edge;
        for (ll i=1; i<=k; i++)
        {
            scanf("%I64d%I64d",&E[i].v,&E[i].w);
            addedge(1,E[i].v,E[i].w);
        }
    }
    
    void SPFA()
    {
        Q[bot=top=1]=1,d[1]=0,iq[1]=true;
        while (bot<=top)
        {
            ll cur=Q[bot++];
            iq[cur]=false;
            for (ll i=first[cur]; i!=-1; i=next[i])
                if (d[cur]+c[i]<d[to[i]])
                {
                    d[to[i]]=d[cur]+c[i];
                    if (!iq[to[i]]) Q[++top]=to[i],iq[to[i]]=true;
                }
        }
    }
    
    void bfs()
    {
        ll topeg=0;
        sort(E+1,E+1+k,cmp);
        for (ll i=1; i<=n; i++) iq[i]=false;
        Q[bot=top=1]=1,iq[1]=true;
        while (bot<=top || topeg<k)
        {
            if (bot<=top)
            {
                ll cur=Q[bot++];
                for (ll i=first[cur]; i!=-1; i=next[i])
                    if (i<=tk && d[cur]+c[i]==d[to[i]] && !iq[to[i]])
                        iq[to[i]]=true,Q[++top]=to[i];
            }
            else
            {
                topeg++;
                if (iq[E[topeg].v] || d[E[topeg].v]<E[topeg].w) ans++;
                    else iq[E[topeg].v]=true,Q[++top]=E[topeg].v;
            }
        }
    }
    
    int main()
    {
        inf*=inf;
        _init();
        SPFA();
        bfs();
        printf("%I64d
    ",ans);
        return 0;
    }
  • 相关阅读:
    So easy Webservice 2.WebService介绍
    So easy Webservice 1.Socket建设web服务
    eclipse 实用快捷键
    Memory Layout of C Programs
    C程序员必须知道的内存知识【英】
    闭包,懂不懂由你,反正我是懂了
    什么是闭包,我的理解
    浅析Java中的访问权限控制
    Java访问控制
    Java修饰符public,private,protected及默认的区别
  • 原文地址:https://www.cnblogs.com/lochan/p/3858341.html
Copyright © 2020-2023  润新知