您的位置:首页 > 其它

Codeforces Round #302 (Div. 2) D bfs最短路

2016-07-25 13:41 405 查看
链接:戳这里

D. Destroying Roads

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
In some country there are exactly n cities and m bidirectional roads connecting the cities. Cities are numbered with integers from 1 to n. If cities a and b are connected by a road, then in an hour you can go along this road either from city a to city b, or
from city b to city a. The road network is such that from any city you can get to any other one by moving along the roads.

You want to destroy the largest possible number of roads in the country so that the remaining roads would allow you to get from city s1 to city t1 in at most l1 hours and get from city s2 to city t2 in at most l2 hours.

Determine what maximum number of roads you need to destroy in order to meet the condition of your plan. If it is impossible to reach the desired result, print -1.

Input

The first line contains two integers n, m (1 ≤ n ≤ 3000, ) — the number of cities and roads in the country, respectively.

Next m lines contain the descriptions of the roads as pairs of integers ai, bi (1 ≤ ai, bi ≤ n, ai ≠ bi). It is guaranteed that the roads that are given in the description can transport you from any city to any other one. It is guaranteed that each pair of
cities has at most one road between them.

The last two lines contains three integers each, s1, t1, l1 and s2, t2, l2, respectively (1 ≤ si, ti ≤ n, 0 ≤ li ≤ n).

Output

Print a single number — the answer to the problem. If the it is impossible to meet the conditions, print -1.

Examples

input

5 4

1 2

2 3

3 4

4 5

1 3 2

3 5 2

output

0

input

5 4

1 2

2 3

3 4

4 5

1 3 2

2 4 2

output

1

input

5 4

1 2

2 3

3 4

4 5

1 3 2

3 5 1

output

-1

题意:

给出n个点m条双向边,边权为1,现在要求删除最多的边,使得只要保证剩下的边满足s1->t1<=l1 && s2->t2<=l2

思路:

n<=3000 m<=3000,暴力bfs,复杂度n*mlogn 算出任意点到点直接的最短路

s1->t1和s2->t2两条路径肯定在走剩下的边的路径长度,不超过l1、l2的情况下,重复使用更多的边会使得答案更优

枚举重复走的路径i->j,去使用最小的边作为最优值

这里注意一点点,就是枚举i->j的时候,由于是双向边。所以需要计算的最小值有四种情况,分别是

s1->i->j->t1 s2->i->j->t2

s1->i->j->t1 t2->i->j->s2

t1->i->j->s1 s2->i->j->t2

t1->i->j->s1 t2->i->j->s2

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include <ctime>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<iomanip>
#include<cmath>
#define mst(ss,b) memset((ss),(b),sizeof(ss))
#define maxn 0x3f3f3f3f
#define MAX 1000100
///#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long ll;
typedef unsigned long long ull;
#define INF (1ll<<60)-1
using namespace std;
int n,m;
struct edge{
int v,next,w;
}e[6060];
int head[3030],tot=0;
void Add(int u,int v,int w){
e[tot].v=v;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot++;
}
int s1,t1,l1,s2,t2,l2;
int dis[3030],d[3030][3030],vis[3030];
struct node{
int v,d;
node(int v=0,int d=0):v(v),d(d){}
bool operator <(const node &a)const{
return d>a.d;
}
};
void BFS(int st){
priority_queue<node > qu;
while(!qu.empty()) qu.pop();
for(int i=1;i<=n;i++) dis[i]=1e9;
mst(vis,0);
dis[st]=0;
qu.push(node(st,0));
while(!qu.empty()){
node now=qu.top();
qu.pop();
vis[now.v]=1;
for(int i=head[now.v];i!=-1;i=e[i].next){
int v=e[i].v;
if(!vis[v] &&dis[v]>dis[now.v]+e[i].w){
dis[v]=dis[now.v]+e[i].w;
qu.push(node(v,dis[v]));
}
}
}
for(int i=1;i<=n;i++) d[st][i]=dis[i];
}
int main(){
mst(head,-1);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
Add(u,v,1);
Add(v,u,1);
}
scanf("%d%d%d",&s1,&t1,&l1);
scanf("%d%d%d",&s2,&t2,&l2);
for(int i=1;i<=n;i++) BFS(i);
if(d[s1][t1]>l1 || d[s2][t2]>l2){
cout<<-1<<endl;
return 0;
}
int ans=d[s1][t1]+d[s2][t2];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(d[s1][i]+d[i][j]+d[j][t1]<=l1 && d[s2][i]+d[i][j]+d[j][t2]<=l2)
ans=min(ans,d[s1][i]+d[s2][i]+d[i][j]+d[j][t1]+d[j][t2]);
if(d[s1][i]+d[i][j]+d[j][t1]<=l1 && d[t2][i]+d[i][j]+d[j][s2]<=l2)
ans=min(ans,d[s1][i]+d[t2][i]+d[i][j]+d[j][t1]+d[j][s2]);
if(d[t1][i]+d[i][j]+d[j][s1]<=l1 && d[s2][i]+d[i][j]+d[j][t2]<=l2)
ans=min(ans,d[t1][i]+d[s2][i]+d[i][j]+d[j][s1]+d[j][t2]);
if(d[t1][i]+d[i][j]+d[j][s1]<=l1 && d[t2][i]+d[i][j]+d[j][s2]<=l2)
ans=min(ans,d[t1][i]+d[t2][i]+d[i][j]+d[j][s1]+d[j][s2]);
}
}
printf("%d\n",m-ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: