题意:给定n个点m条边的无向图(边权全为1),让你去掉最多的边使得d(s1, t1) <= l1 && d(s2, t2) <= l2,若不能满足输出-1,反之输出可以去掉的最多边数。
思路:SPFA预处理所有点之间的距离。求出在满足d(s1, t1) <= l1 && d(s2, t2) <= l2的前提下,路径需要的最少边数ans,答案就是m - ans。
方法是:用dist[i][j]存储最短路。枚举d(s1, t1) 和 d(s2, t2)这两条路径上可能重合的路径d(i, j)
(1)D1=dist[s1][i] + dist[i][j] + dist[j][t1] <= l1 && D2=dist[s2][i] + dist[i][j] + dist[j][t2] <= l2
(2)D1=dist[s1][i] + dist[i][j] + dist[j][t1] <= l1 && D2=dist[s2][j] + dist[j][i] + dist[i][t2] <= l2
(3)D1=dist[s1][j] + dist[j][i] + dist[i][t1] <= l1 && D2=dist[s2][i] + dist[i][j] + dist[j][t2] <= l2
(4)D1=dist[s1][j] + dist[j][i] + dist[i][t1] <= l1 && D2=dist[s2][j] + dist[j][i] + dist[i][t2] <= l2
更新答案为ans = min(ans, D1 + D2 - dist[i][j])。
AC代码;
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (3000+10)
#define MAXM (50000000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
using namespace std;
struct Edge{
int from, to, next;
};
Edge edge[MAXN*MAXN];
int head[MAXN], edgenum;
bool vis[MAXN];
int dist[MAXN][MAXN];
void init(){
edgenum = 0;
CLR(head, -1);
}
void addEdge(int u, int v)
{
Edge E = {u, v, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
void SPFA(int s, int *d)
{
queue<int> Q;
CLR(vis, false);
d[s] = 0; vis[s] = true; Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
vis[u] = false;
for(int i = head[u]; i != -1; i = edge[i].next)
{
Edge E = edge[i];
if(d[E.to] > d[u] + 1)
{
d[E.to] = d[u] + 1;
if(!vis[E.to])
{
vis[E.to] = true;
Q.push(E.to);
}
}
}
}
}
int main()
{
int n, m;
Ri(n); Ri(m); init();
for(int i = 0; i < m; i++)
{
int a, b; Ri(a); Ri(b);
addEdge(a, b); addEdge(b, a);
}
int s1, t1, l1, s2, t2, l2;
Ri(s1); Ri(t1); Ri(l1);
Ri(s2); Ri(t2); Ri(l2);
CLR(dist, INF);
for(int i = 1; i <= n; i++)
SPFA(i, dist[i]);
if(dist[s1][t1] > l1 || dist[s2][t2] > l2)
printf("-1\n");
else
{
int ans = dist[s1][t1] + dist[s2][t2];
for(int i = 1; i <= n; i++)
{
for(int j = i+1; j <= n; j++)
{
if(dist[s1][i]+dist[i][j]+dist[j][t1] <= l1 && dist[s2][i]+dist[i][j]+dist[j][t2] <= l2)
ans = min(ans, dist[s1][i]+dist[i][j]+dist[j][t1]+dist[s2][i]+dist[j][t2]);
if(dist[s1][i]+dist[i][j]+dist[j][t1] <= l1 && dist[s2][j]+dist[j][i]+dist[i][t2] <= l2)
ans = min(ans, dist[s1][i]+dist[i][j]+dist[j][t1]+dist[s2][j]+dist[i][t2]);
if(dist[s1][j]+dist[j][i]+dist[i][t1] <= l1 && dist[s2][i]+dist[i][j]+dist[j][t2] <= l2)
ans = min(ans, dist[s1][j]+dist[j][i]+dist[i][t1]+dist[s2][i]+dist[j][t2]);
if(dist[s1][j]+dist[j][i]+dist[i][t1] <= l1 && dist[s2][j]+dist[j][i]+dist[i][t2] <= l2)
ans = min(ans, dist[s1][j]+dist[j][i]+dist[i][t1]+dist[s2][j]+dist[i][t2]);
}
}
Pi(m-ans);
}
return 0;
}