CF543B Destroying Roads

发布时间 2023-10-18 20:11:52作者: 空気力学の詩

好经典的题,因为暑假前集训做过类似的思想的题所以知道怎么处理

这题由于要求最多的删去的边数,则等价于求最少保留几条边,很显然留下的边一定是最短路上的

但问题是如果两条路不相交的话很简单,可事实是两条路径可以重叠一些部分,这些边用了两次可能可以使答案变优

关于这种图上两条路径的题有一个经典结论,即两条路径至多相交一次

具体地,我们可以枚举两条路径的重复部分\(x,y\),则最后两条路径分别为\(s_1\to x\to y\to t_1,s_2\to x\to y\to t_2\)(当然具体的顺序可以换一下)

预处理出任意两点的最短路后就很简单了,总复杂度\(O(n^2)\)

#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef __int128 i128;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=3005,INF=1e9;
int n,m,x,y,s1,t1,l1,s2,t2,l2,dis[N][N]; vector <int> v[N];
inline void BFS(CI st,int* d)
{
	for (RI i=1;i<=n;++i) d[i]=INF;
	queue <int> q; q.push(st); d[st]=0;
	while (!q.empty())
	{
		int now=q.front(); q.pop();
		for (auto to:v[now]) if (d[to]>d[now]+1)
		d[to]=d[now]+1,q.push(to);
	}
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i,j; for (scanf("%d%d",&n,&m),i=1;i<=m;++i)
	scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
	for (i=1;i<=n;++i) BFS(i,dis[i]);
	scanf("%d%d%d%d%d%d",&s1,&t1,&l1,&s2,&t2,&l2);
	if (dis[s1][t1]>l1||dis[s2][t2]>l2) return puts("-1"),0;
	int ans=dis[s1][t1]+dis[s2][t2];
	auto Dis=[&](CI s,CI t)
	{
		return min(dis[s][i]+dis[j][t],dis[s][j]+dis[i][t])+dis[i][j];
	};
	for (i=1;i<=n;++i) for (j=1;j<=n;++j)
	if (Dis(s1,t1)<=l1&&Dis(s2,t2)<=l2)
	ans=min(ans,Dis(s1,t1)+Dis(s2,t2)-dis[i][j]);
	return printf("%d",m-ans),0;
}