la4080 Warfare And Logistics 枚舉+最短路

      給一個圖,求出任意兩點的最短路之和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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章