luogu P5683 [CSPJX2019]道路拆除

题面传送门
这次 J X JX JX重考的题目也太水了点吧,完全比不上原来的 T 3 T3 T3
题目要求拆除的边数最多,那么要留下的边数最少。
那么这样的话 1 1 1 s 1 s1 s1 s 2 s2 s2的路程中最好有一部分是重叠的。
1 1 1 s 1 s1 s1 s 2 s2 s2的路程均为一条链,这两条链可能有一部分是重叠的。无论重叠也好,不重叠也好,总会有一个交点,这个交点通了至少 2 2 2条路径。
所以我们可以枚举交点。
我们可以在预处理的过程中从 1 1 1 s 1 s1 s1 s 2 s2 s2各跑一遍 S P F A SPFA SPFA,众所周知,边权为 1 1 1的图肯定卡不了 S P F A SPFA SPFA,所以我们可以使用。
代码实现:

#include
#include
#include
using namespace std;
int n,m,k,h[5039],head,d1[5039],d2[5039],d3[5039],s1,s2,t1,t2,now,cur,x,y,z,ans=-1;
struct yyy{
	int to,z;
}tmp,f[10039];
inline void add(int x,int y){
	f[++head]=(yyy){y,h[x]};
	h[x]=head;
}
queue<int> q;
int main(){
	register int i;
	scanf("%d%d",&n,&m);
	memset(h,-1,sizeof(h));
	memset(d1,0x3f,sizeof(d1));
	memset(d2,0x3f,sizeof(d2));
	memset(d3,0x3f,sizeof(d3));
	for(i=1;i<=m;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
	scanf("%d%d%d%d",&s1,&t1,&s2,&t2);
	d1[s1]=d2[s2]=d3[1]=0;
	q.push(s1);
	while(!q.empty()){
		now=q.front();
		q.pop();
		cur=h[now];
		while(cur!=-1){
			tmp=f[cur];
			if(d1[tmp.to]>d1[now]+1) d1[tmp.to]=d1[now]+1,q.push(tmp.to);
			cur=tmp.z;
		}
	}
	q.push(s2);
	while(!q.empty()){
		now=q.front();
		q.pop();
		cur=h[now];
		while(cur!=-1){
			tmp=f[cur];
			if(d2[tmp.to]>d2[now]+1) d2[tmp.to]=d2[now]+1,q.push(tmp.to);
			cur=tmp.z;
		}
	}
	q.push(1);
	while(!q.empty()){
		now=q.front();
		q.pop();
		cur=h[now];
		while(cur!=-1){
			tmp=f[cur];
			if(d3[tmp.to]>d3[now]+1) d3[tmp.to]=d3[now]+1,q.push(tmp.to);
			cur=tmp.z;
		}
	}
	for(i=1;i<=n;i++){
		if(d1[i]+d3[i]<=t1&&d2[i]+d3[i]<=t2&&m-d1[i]-d2[i]-d3[i]>ans) ans=m-d1[i]-d2[i]-d3[i];
	}
	printf("%d\n",ans);
}

你可能感兴趣的:(洛谷)