您的位置:首页 > 其它

Codeforces 544D Destroying Roads【思维枚举+最短路】好题~好题!

2017-06-14 14:52 507 查看
D. Destroying Roads

time limit per test
2 seconds

memory limit per test
256 megabytes

input
standard input

output
standard 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条无向边的图。

让你确定最多可以去掉多少条边,使得从s1到t1的最短距离小于等于l1,并且使得从s2到t2的最短距离小于等于l2.

思路:

很显然,我们用的边越少,可以去掉的边就越多,问我们最多可以去掉多少条边,其实也就是再问我们最少用多少条边。

如果两条路没有相交重叠的部分,那么我们的最初答案肯定就是m-dist[s1][t1]-dist[s2][t2];

那么我们如何进行优化呢?使得使用的边尽可能的少呢?

答案很简单,我们希望两条路有重叠的部分。

又不难想到,对于两条路的重叠部分,其没有必要具有大于1段(交汇了之后如果再散开了就没有必要再汇在一起了,因为如果还有必要汇在一起的话就没有必要散开)。

再观察到数据范围N不是很大,所以我们可以O(n^2)来枚举重叠部分的起点和终点。

那么我们需要知道两点之间最短路,又因为每条边的长度都是1.那么其实SPFA是一个更好的选择(其实就变成了Bfs,O(n^2+m));

那么整理一下思路:

①我们SPFA预处理出两点间最短路。

②然后我们O(n^2)枚举重叠部分的起点和终点。

③然后判断两条路经过重叠部分是否都小于其各自的限制(l1,l2);

④维护答案。

这里注意一点:可能会存在重叠路径相反走向的情况,也就是说对于枚举出来的重叠部分两点u,v,对于两条路来讲,可能有一条从u-->v,另一条从v--->u.

所以枚举的时候再颠倒几次都判断一下即可。

Ac代码:

#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
vector<int >mp[3500];
int dist[3500][3500];
int vis[3500];
int n,m;
void SPFA(int ss,int d)
{
for(int i=1;i<=n;i++)dist[d][i]=0x3f3f3f3f;
dist[d][ss]=0;
memset(vis,0,sizeof(vis));
queue<int >s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
vis[u]=0;
s.pop();
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(dist[d][v]>dist[d][u]+1)
{
dist[d][v]=dist[d][u]+1;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
mp[x].push_back(y);
mp[y].push_back(x);
}
int s,t,len;
int ss,tt,lenn;
scanf("%d%d%d%d%d%d",&s,&t,&len,&ss,&tt,&lenn);
for(int i=1;i<=n;i++)
{
SPFA(i,i);
}
if(dist[s][t]>len||dist[ss][tt]>lenn)
{
printf("-1\n");
}
else
{
int output=m-dist[s][t]-dist[ss][tt];
if(output<0)output=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dist[s][i]+dist[i][j]+dist[j][t]<=len)
{
if(dist[ss][i]+dist[i][j]+dist[j][tt]<=lenn)
{
output=max(output,m-dist[i][j]-dist[s][i]-dist[ss][i]-dist[j][t]-dist[j][tt]);
}
}
if(dist[s][j]+dist[j][i]+dist[i][t]<=len)
{
if(dist[ss][i]+dist[i][j]+dist[j][tt]<=lenn)
{
output=max(output,m-dist[i][j]-dist[s][j]-dist[ss][i]-dist[i][t]-dist[j][tt]);
}
}
if(dist[s][i]+dist[i][j]+dist[j][t]<=len)
{
if(dist[ss][j]+dist[j][i]+dist[i][tt]<=lenn)
{
output=max(output,m-dist[i][j]-dist[s][i]-dist[ss][j]-dist[j][t]-dist[i][tt]);
}
}
if(dist[s][j]+dist[j][i]+dist[i][t]<=len)
{
if(dist[ss][j]+dist[j][i]+dist[i][tt]<=lenn)
{
output=max(output,m-dist[j][i]-dist[s][j]-dist[ss][j]-dist[i][t]-dist[i][tt]);
}
}
}
}
printf("%d\n",output);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Codeforces 544D