2020杭电多校三 1007 Tokitsukaze and Rescue

http://acm.hdu.edu.cn/showproblem.php?pid=6797
题意:最多50个点的完全图,删k(最多5)条边,求最大的最短路,边权范围内随机。
思路:先删一条边,必定有一条在最短路上,否则走这条还是最短。删这条边后,再找最短路,再删一边一定是在这次的最短路是,否则走这条还是最短,这样递归k层。复杂度是 O ( n 2 ∗ n k ) O(n^2 * n^k) O(n2nk),最大 2500 ∗ 5 0 5 2500*50^5 2500505,看似不行,实际上就是暴力,因为边权随机,所以大部分最短路都比较短。
2020杭电多校三 1007 Tokitsukaze and Rescue_第1张图片

#include
using namespace std;
const int INF=0x3f3f3f3f;

int T,n,k,d[55][55];
bool link[55][55];
int dis[55],in[55],from[55];
int ans;

void spfa()
{
	queue<int> q;
	for(int i=2;i<=n;i++)
		dis[i]=INF;
	dis[1]=0;in[1]=true;q.push(1);
	int u,v;
	while(!q.empty())
	{
		u=q.front();q.pop();
		for(v=1;v<=n;v++)
			if(link[u][v] && dis[v]>dis[u]+d[u][v])
			{
				dis[v]=dis[u]+d[u][v];from[v]=u;
				if(!in[v])
					in[v]=true,q.push(v);
			}
		in[u]=false;
	}
}

void dfs(int x)
{
	if(x>k)
	{
		spfa();
		ans=max(ans,dis[n]);
		return;
	}
	spfa();
	int u=n;
	vector<int> path;
	while(u)
	{
		path.push_back(u);
		u=from[u];
	}
	for(int i=0;i<path.size()-1;i++)
	{
		link[path[i]][path[i+1]]=link[path[i+1]][path[i]]=0;
		dfs(x+1);
		link[path[i]][path[i+1]]=link[path[i+1]][path[i]]=1;
	}

}

int main()
{
	//freopen("input.in","r",stdin);
	cin>>T;
	while(T--)
	{
		cin>>n>>k;
		int u,v,w;
		for(int i=1;i<=n*(n-1)/2;i++)
		{
			cin>>u>>v>>w;
			d[u][v]=d[v][u]=w;
			link[u][v]=link[v][u]=1;
		}
		ans=0;
		dfs(1);
		cout<<ans<<endl;
	}
}

你可能感兴趣的:(最短路)