关键词:bfs求单源最短路径、O(n^2)枚举相交路径
题意:在一个有向图中删除尽量多的边使得s1->t1,s2->t2的最短路分别不大于l1和l2
解法:
1.bfs求单源最短路径。遍历所有的顶点,求出所有点源最短路
2.枚举两条道路的相交路径。相交路径仅加一次即可
思路分析:
从删边后的结果出发,s1->t1,s2->t2有一段相交路径,其余部分不相交。要使删边最大,就要使留下的边长和最小。因此
s1->t1,s2->t2均由三条最短路组成。枚举中间的那条最短路两端点维护剩余图的最小边长和。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#define mem(a,b) memset(a,sizeof(a),b)
#define ll long long
using namespace std;
const int maxn = 3000+10;
int n,m;
vector<int> e[maxn];
int s[2],t[2],l[2];
int ans;
int d[maxn][maxn];
void bfs(int x){
queue<int> q;
for(int i=1;i<=n;i++) d[x][i]=-1;
q.push(x),d[x][x]=0;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=0;i<e[u].size();i++){
int v=e[u][i];
if(d[x][v]==-1){
d[x][v]=d[x][u]+1;
q.push(v);
}
}
}
}
int main(){
//freopen("a.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
e[a].push_back(b),e[b].push_back(a);
}
for(int i=1;i<=n;i++) bfs(i);
for(int i=0;i<2;i++) scanf("%d%d%d",&s[i],&t[i],&l[i]);
if(d[s[0]][t[0]]>l[0]||d[s[1]][t[1]]>l[1]){
printf("-1\n");
return 0;
}
ans=d[s[0]][t[0]]+d[s[1]][t[1]];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int l1=d[s[0]][i]+d[i][j]+d[j][t[0]],l2=d[s[0]][j]+d[j][i]+d[i][t[0]];
int l3=d[s[1]][i]+d[i][j]+d[j][t[1]];
if(l1<=l[0]&&l3<=l[1]) ans=min(ans,l1+d[s[1]][i]+d[j][t[1]]);
if(l2<=l[0]&&l3<=l[1]) ans=min(ans,l2+d[s[1]][i]+d[j][t[1]]);
}
}
printf("%d\n",m-ans);
}