1. 程式人生 > >Codeforces 544D Destroying Roads【思維列舉+最短路】好題~好題!

Codeforces 544D Destroying Roads【思維列舉+最短路】好題~好題!

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);
        }
    }
}