题意:对于给定的图,求最多删除多少边,使得s1-t1的距离不超过l1,s2-t2的距离不超过l2。
思路:首先可以通过bfs在n^2的复杂度下求出dis[i][j]的最短距离,然后枚举中间重叠的部分的点u和v。如果有重叠的话,最短距离为dis[s1][u]+dis[s2][u]+dis[u][v]+dis[v][t1]+dis[v][t2]或者dis[s1][u]+dis[t2][u]+dis[u][v]+dis[v][t1]+dis[v][s2]。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
struct node
{
int v,next;
}edge[6010];
int n,m;
int dis[3010][3010],Head[3010],tot,INF=1e9;
int s1,s2,t1,t2,d1,d2;
bool vis[3010];
queue<int> qu;
void add(int u,int v)
{
edge[tot].v=v;
edge[tot].next=Head[u];
Head[u]=tot++;
}
int main()
{
int i,j,k,u,v,ans;
scanf("%d%d",&n,&m);
memset(Head,-1,sizeof(Head));
for(i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
scanf("%d%d%d%d%d%d",&s1,&t1,&d1,&s2,&t2,&d2);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
dis[i][j]=INF;
for(i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
dis[i][i]=0;
vis[i]=1;
qu.push(i);
while(!qu.empty())
{
u=qu.front();
qu.pop();
for(j=Head[u];j!=-1;j=edge[j].next)
{
v=edge[j].v;
if(vis[v])
continue;
dis[i][v]=dis[i][u]+1;
vis[v]=1;
qu.push(v);
}
}
}
if(dis[s1][t1]>d1 || dis[s2][t2]>d2)
{
printf("-1\n");
return 0;
}
ans=dis[s1][t1]+dis[s2][t2];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
if(dis[s1][i]+dis[i][j]+dis[j][t1]<=d1 && dis[s2][i]+dis[i][j]+dis[j][t2]<=d2)
ans=min(ans,dis[s1][i]+dis[s2][i]+dis[i][j]+dis[j][t1]+dis[j][t2]);
if(dis[s1][i]+dis[i][j]+dis[j][t1]<=d1 && dis[t2][i]+dis[i][j]+dis[j][s2]<=d2)
ans=min(ans,dis[s1][i]+dis[t2][i]+dis[i][j]+dis[j][t1]+dis[j][s2]);
}
printf("%d\n",m-ans);
}