LA 4080 战争和物流(最短路树)

时间:2023-03-09 04:57:16
LA 4080 战争和物流(最短路树)

https://vjudge.net/problem/UVALive-4080

题意:
给出一个n个结点m条边的无向图,每条边上有一个正权。令c等于每对结点的最短路长度之和。不连通的两点的最短路长度视为L。

求出初始时的最短路长度之和以及删除一条边后最大的最短路长度之和。

思路:

最短路树其实很简单,就是用一个二维数组记录某个源点出发所经过的边,如$belong[s][i]$就说明源点s出发经过了i这条边。这样做的好处是当我们枚举删除的边的时候,如果它不在当前源点的最短路树上,那么对于最短路不会有影响,如果在,那么此时就要重新跑最短路。这样可以节约很多时间。

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<bitset>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const ll INF = (ll)<<;
const int maxn=+; int n,m,tot,l;
ll ans;
int head[maxn];
bool vis[maxn],del[],belong[maxn][];
ll d[maxn],w[maxn];
int p[maxn]; struct node
{
int id,v,d,next;
}e[maxn*maxn]; struct HeapNode
{
int u; ll d;
HeapNode(int u, ll d):u(u),d(d){}
bool operator<(const HeapNode& rhs) const
{
return d>rhs.d;
}
}; void addEdge(int id, int u, int v, int d)
{
e[tot].id=id;
e[tot].d=d;
e[tot].v=v;
e[tot].next=head[u];
head[u]=tot++;
} void dijkstra1(int s)
{
priority_queue<HeapNode> Q;
memset(vis,false,sizeof(vis));
for(int i=;i<=n;i++) d[i]=INF;
d[s]=;
Q.push(HeapNode(s,));
while(!Q.empty())
{
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if(vis[u]) continue;
belong[s][p[u]]=true;
vis[u]=true;
for(int i=head[u];i!=-;i=e[i].next)
{
int v=e[i].v;
if(d[v]>d[u]+e[i].d)
{
d[v]=d[u]+e[i].d;
p[v]=e[i].id;
Q.push(HeapNode(v,d[v]));
}
}
}
for(int i=;i<=n;i++)
{
if(d[i]==INF)
{
w[s]+=l;
ans+=l;
}
else
{
w[s]+=d[i];
ans+=d[i];
}
}
} ll dijkstra2(int s)
{
priority_queue<HeapNode> Q;
memset(vis,false,sizeof(vis));
for(int i=;i<=n;i++) d[i]=INF;
d[s]=;
Q.push(HeapNode(s,));
while(!Q.empty())
{
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if(vis[u]) continue;
vis[u]=true;
for(int i=head[u];i!=-;i=e[i].next)
{
int v=e[i].v;
if(del[e[i].id]) continue;
if(d[v]>d[u]+e[i].d)
{
d[v]=d[u]+e[i].d;
Q.push(HeapNode(v,d[v]));
}
}
}
ll tmp=;
for(int i=;i<=n;i++)
{
if(d[i]==INF) tmp+=l;
else tmp+=d[i];
}
return tmp;
} int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d%d",&n,&m,&l))
{
tot=;
memset(head,-,sizeof(head));
memset(del,false,sizeof(del));
memset(belong,false,sizeof(belong));
memset(w,,sizeof(w));
for(int i=;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addEdge(i,u,v,w);
addEdge(i,v,u,w);
}
ans=;
for(int i=;i<=n;i++) dijkstra1(i);
printf("%lld ",ans);
ans=;
for(int i=;i<=m;i++)
{
ll tmp=;
del[i]=true;
for(int j=;j<=n;j++)
{
if(belong[j][i]) tmp+=dijkstra2(j);
else tmp+=w[j];
}
del[i]=false;
ans=max(ans,tmp);
}
printf("%lld\n",ans);
}
return ;
}