la4080 Warfare And Logistics 枚举+最短路

来源:互联网 发布:淘宝原单尾货是正品吗 编辑:程序博客网 时间:2024/06/05 01:53

      给一个图,求出任意两点的最短路之和ans1,和删除一条边和,可以得到的最大的任意两点间的最短路之和ans2,若两点不连通,则两点间最短距离视为l。

第一想法就是枚举每条边,然后跑n次最短路,但这样的复杂度是1000*1000*100*log(100),太大了..其实在固定起点,求出单元最短路的时候,同时可以求出单源最短路树,只有删除的边在树上的时候,源点到任一点的最短路才会有变化,所以在每次跑单源最短路的时候,只需要枚举树上的n-1条边就可以了。累加一下删除每一条边时,在当前源点的情况下,最短距离之和的增加量,最后枚举找一条增加量最大的边就可以了。

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <queue>#include <cstring>#include <vector>using namespace std;typedef long long ll;const ll inf=(1LL<<61);ll cost[2020];int n,m;ll l;struct HeapNode{    ll d;    int u;    bool operator< (const HeapNode& rhs) const    {        return d>rhs.d;    }    HeapNode(){}    HeapNode(ll x,int y)    {        d=x;        u=y;    }};struct Edge{    int u,v;    ll w;    bool ok;    Edge(){}    Edge(int x,int y,ll z)    {        u=x;        v=y;        w=z;        ok=true;    }};const int maxn=105;struct Dij{    int n,m;    vector<Edge> edges;    vector<int> G[maxn];    bool done[maxn];    ll d[maxn];    int p[maxn];    void init(int n)    {        this->n=n;        for (int i=0; i<=n; i++)        {            G[i].clear();        }        edges.clear();    }    void addedge(int x,int y,ll z)    {        edges.push_back((Edge(x,y,z)));        m=edges.size();        G[x].push_back(m-1);    }    void dijkstra(int s)    {        priority_queue<HeapNode> q;        for (int i=0; i<=n; i++)        d[i]=inf;        d[s]=0;        memset(done,0,sizeof done);        memset(p,-1,sizeof p);        q.push(HeapNode(0,s));        while(!q.empty())        {            HeapNode x=q.top(); q.pop();            int u=x.u;            if (done[u]) continue;            done[u]=true;            for (int i=0; i<G[u].size(); i++)            {                Edge &e=edges[G[u][i]];                if (!e.ok) continue;                if (d[e.v]>d[u]+e.w)                {                    d[e.v]=d[u]+e.w;                    p[e.v]=G[u][i];                    q.push(HeapNode(d[e.v],e.v));                }            }        }    }    int tp[maxn];    ll slove(int s)    {        ll res=0;        ll add=0;        ll tmp=0;        ll maxx=0;        for (int i=1; i<=n; i++)        {            if (d[i]<inf)res+=d[i];            else res+=l;        }        memcpy(tp,p,sizeof p);        for (int i=1;i<=n; i++)        {            if (tp[i]!=-1)            {                edges[tp[i]].ok=false;                edges[tp[i]^1].ok=false;                dijkstra(s);                tmp=0;                for (int j=1; j<=n; j++)                {                  if (d[j]<inf) tmp+=d[j];                  else tmp+=l;                }                cost[tp[i]]+=(tmp-res);                cost[tp[i]^1]+=(tmp-res);                edges[tp[i]].ok=true;                edges[tp[i]^1].ok=true;            }        }        return res;    }}work;int main(){//    freopen("in.txt","r",stdin);    while (~scanf("%d%d%lld",&n,&m,&l))    {        int x,y;        ll z;        work.init(n);        for (int i=1; i<=m; i++)        {            scanf("%d%d%lld",&x,&y,&z);            work.addedge(x,y,z);            work.addedge(y,x,z);        }        memset(cost,0,sizeof cost);        ll ans=0;        for (int i=1; i<=n; i++)        {            work.dijkstra(i);            ans+=work.slove(i);        }        int id=0;        ll maxx=0;        ll ans2=0;        for (int i=0; i<work.edges.size(); i++)        {            if (cost[i]>maxx)            {                id=i;                maxx=cost[i];            }        }        work.edges[id].ok=false;        work.edges[id^1].ok=false;        for (int i=1; i<=n; i++)        {            work.dijkstra(i);            for (int j=1; j<=n; j++)            if (work.d[j]<inf) ans2+=work.d[j];            else ans2+=l;        }        cout<<ans<<" "<<ans2<<endl;    }    return 0;}


0 0
原创粉丝点击