Codeforces 296D Greg And Graph (逆向处理)Floyd

点击打开链接

题意:n个点的有向带权完全图,第i次删除一个点及其所有的边,
n<=500,求删除xi之前,任意两点最短距离的累加和,  ? 



逆着考虑:相当于每次添加一个结点后,在更新最短路径.O(n^3)

对第m个新加入的点x,n^2更新x(出发/结尾)时中间点编号为后m+1个的d^(m+1)值 在n^2更更新中间点为x时的d^m值即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-10;
const int inf=0x3f3f3f3f;
const int N=5e2+20;
ll g[N][N],d[N][N],n,a[N];
vector<ll> ans;
void solve()
{
	ans.clear();
	ans.push_back(0);
	int m=1;
	while(m<n)
	{
		ll res=0;	
		for(int k=n-m;k<=n;k++)
		{
			for(int i=n-m;i<=n;i++)
			{
				int u=a[k],v=a[i],x=a[n-m];
				d[x][v]=min(d[x][v],d[x][u]+d[u][v]);
				d[v][x]=min(d[v][x],d[v][u]+d[u][x]);
			}
		}
		for(int i=n-m;i<=n;i++)
		{
			for(int j=n-m;j<=n;j++)
			{
				int u=a[i],v=a[j],x=a[n-m];	
				d[u][v]=min(d[u][v],d[u][x]+d[x][v]);
				res+=d[u][v];
			}		
		}
		m++;
		ans.push_back(res);
	}
	for(int i=ans.size()-1;i>=0;i--)
		printf("%I64d ",ans[i]);
	printf("\n");
}
int main()
{
	while(cin>>n)
	{
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				scanf("%I64d",&d[i][j]);
		for(int i=1;i<=n;i++)
			scanf("%I64d",&a[i]);
		solve();
	}
	return 0;
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值