题意:给一个n个节点m条边的无向图,求每个点到所有点的最短距离之和,如n=3时,答案是c=d[1][2]+d[1][3]+d[2][1]+ d[2][3]+d[3][1]+d[3][2],不联通的两点距离为L,还要求删除一条边后的最大的c'。
思路:每次dij()算法求出每个点到所有点的最短距离和,有n个点,复杂度nmlogn,还需要删除每条边再求这么多c',复杂度为nm^2logn,复杂度太高,但是每次求出某点到所有点的的最短距离和之后,可以把这颗最短路树的边标记,下次删除边时,只有删除n-1个边,因为删除其他边,求该点的最短路和等于没删边的值,这样下来复杂度为mn^2logn,不过有个巨大的坑,题目说不联通的两点距离为L,因此在开始的时候就要把所有未直接连通的两点加一条权值为L的边。
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=105;
typedef long long LL;
const LL inf=1e14;
struct node
{
int u,num;//num为边的编号
long long dist;
bool friend operator<(node c,node d)
{
return c.dist>d.dist;
}
}no,ne;
vector<node>G[maxn];
int vis[maxn],vis1[11100],link[maxn][maxn];
LL d[maxn],c[maxn][11100],ans1,ans2,L;
int n,m,tot;
void init()
{
for(int i=1;i<=n;i++)
{
G[i].clear();
memset(link[i],0,sizeof(link[i]));
}
ans1=ans2=0;
}
LL dij(int s,int flag)
{
for(int i=1;i<=n;i++)
{
vis[i]=0;
d[i]=inf;
}
priority_queue<node>q;
no.u=s,no.dist=0;
q.push(no);
d[s]=0;
while(!q.empty())
{
no=q.top();q.pop();
if(vis[no.u])
continue;
vis[no.u]=1;
if(flag==0&&no.u!=s)
vis1[no.num]=1;//标记最短路树的边
int u=no.u;
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].u;
LL tmp=G[u][i].dist;
if(G[u][i].num==flag)//要删除的边
tmp=L;
if(d[v]>d[u]+tmp)
{
d[v]=d[u]+tmp;
ne.dist=d[v];
ne.num=G[u][i].num;
ne.u=v;
q.push(ne);
}
}
}
LL sum=0;
for(int i=1;i<=n;i++)
sum+=d[i];
return sum;
}
void work()
{
for(int i=1;i<=n;i++)
{
memset(vis1,0,sizeof(vis1));
LL t=dij(i,0);
ans1+=t;
for(int j=1;j<=tot;j++)
c[i][j]=t;
for(int j=1;j<=tot;j++)
if(vis1[j]==1)
c[i][j]=dij(i,j);
}
for(int i=1;i<=tot;i++)
{
LL sum=0;
for(int j=1;j<=n;j++)
sum+=c[j][i];
ans2=max(ans2,sum);
}
}
int main()
{
int u,v;
LL len;
while(~scanf("%d%d%lld",&n,&m,&L))
{
init();
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&u,&v,&len);
no.u=u,no.num=i,no.dist=len;
G[v].push_back(no);
no.u=v,no.num=i,no.dist=len;
G[u].push_back(no);
link[u][v]=link[v][u]=1;
}
tot=m;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)//补边
{
if(link[i][j]==1)
continue;
no.u=j,no.num=++tot,no.dist=L;
G[i].push_back(no);
no.u=i,no.num=tot,no.dist=L;
G[j].push_back(no);
}
}
work();
printf("%lld %lld\n",ans1,ans2);
}
}