题目描述:

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.

输入描述:

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).

输出描述:

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

输入样例1:

5 4
1 2
2 3
3 4
4 5
1 3 2
3 5 2

输出样例1:

0

输入样例2:

5 4
1 2
2 3
3 4
4 5
1 3 2
2 4 2

输出样例2:

1

输入样例3:

5 4
1 2
2 3
3 4
4 5
1 3 2
3 5 1

输出样例3:

-1

题目解释:

有1-n共n个点,其中有些点之间有直达路径且路径长度都为1,现在你将输入s1,t1,d1和s2,t2,d2代表从s1到t1不能超过d1距离,从s2到t2不能超过d2距离,在满足这两个条件的情况下你会摧毁多余的路段,现在要求你摧毁尽量多的路段满足该条件,你要输出能摧毁的最多路段的数量。如果不能则输出-1.

题目分析:

这是一道很明显的多源最短路径问题,因为从s1到t1不能超过d1距离,从s2到t2不能超过d2距离,所以我们一定得知道从s1到t1以及从s2到t2的最短距离,如果其中一个的最短距离大于限定距离,则输出-1.否则,我们需要找s1到t1以及s2到t2的重复路径最多的路径,这样,总的s1到t1,s2到t2的距离会相对少,要摧毁的就会相对多。大概思路已经有了,接下来我们要解决的就是求多源最短路径的问题你,相信电脑前的ACMer一定听说或者学会了迪杰特斯拉和佛洛依德算法,也就是单源和多源最短路径算法,但是佛洛依德算法在求多源最短路径时的时间复杂度为O(n^3),这是一个很让人不能忍受的时间复杂度,对于本题的限定条件n=3000时,必定超时,也就是说,不能使用前面两种算法求多源最短路径。那么,我们该用什么方法呢?细心的你一定注意到了,两个点之间只要有路,路径长度必然为1,如此说来,两个有路的点最短路径为1,而相邻的点则通过有路且相邻的点距离+1即可,发现了没有?对于本题特殊的路径相同的情况下,其实我们可以用广度优先搜索(bfs)来求多源最短路径,保存每一个顶点的层数即可,层层求距离,因为每个点在每一次bfs中走且只走1次,因此,其时间复杂度为O(n^2),虽然还是那么不能令人满意,但对于本题的n<=3000来说,够用了。

接下来上AC代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <list>
#include <ctime>
using namespace std;
const int maxn = 3010;
bool vis[maxn];
int d[maxn][maxn],ceng[maxn];//ceng数组保存广度优先搜索的层数
vector <int> edge[maxn];//使用不定长数组vector,其中,每一个顶点i所在的行中d[i][j](j >= 0)保存的是有直接路径的顶点下标
//以每一个顶点为行坐标的数组存放其相邻点下标
void add(int x,int y)
{
    edge[x].push_back(y);//将y保存入edge[x][j]
    edge[y].push_back(x);//同理
}
//////////////////////////////
//广度优先搜索求每个点到其他点的最短路径长度
void bfs(int s)
{
    memset(vis,false,sizeof(vis));
    queue <int>qu;
    qu.push(s);
    vis[s] = true;
    ceng[s] = 0;
    d[s][s] = 0;
    int x,i;
    while (!qu.empty())
    {
        x = qu.front();
        qu.pop();
        for (i = 0; i < edge[x].size(); i++)
        {
            if(!vis[edge[x][i]])
            {
              ceng[edge[x][i]] = ceng[x] + 1;//层数等于父节点的层数+1
              d[s][edge[x][i]] = ceng[edge[x][i]];//距离起点的距离等于层数即可,因为每条路的权值都为1
              qu.push(edge[x][i]);
              vis[edge[x][i]] = true;/将该顶点标记为true,表示该顶点到起点的最短路径已经求出来了
            }
        }
    }
}
int main(void)
{
    int n,m,i,j,u,v,ans,s1,t1,d1,s2,t2,d2;
    scanf ("%d%d",&n,&m);
    for (i = 1; i <= m; i++)
    {
        scanf ("%d%d",&u,&v);
        add(u,v);
    }
    scanf ("%d%d%d%d%d%d",&s1,&t1,&d1,&s2,&t2,&d2);
    for (i = 1; i <= n; i++)
    {
        bfs(i);
    }

//只要s1到t1或s2到t2其中一个的最短路径大于限定条件,输出-1
    if(d[s1][t1] > d1 || d[s2][t2] > d2)
    {
        printf ("-1\n");
        return 0;
    }
    ans = d[s1][t1] + d[s2][t2];
    for (i = 1; i <= n; i++)
    {
        for (j = 1; j <= n; j++)
        {

//这四个条件很关键,这是求重复最多的路径长度的,你可以画个图看一看,其中d[i][j]时s1到t1和s2到t2的重复路径,其实只要走一次就好~
            if(d[s1][i] + d[i][j] + d[j][t1] <= d1 && d[s2][i] + d[i][j] + d[j][t2] <= d2)
            {
                ans = min(ans,d[s1][i] + d[i][j] + d[j][t1] + d[s2][i] + d[j][t2]);
            }
            if(d[t1][i] + d[i][j] + d[j][s1] <= d1 && d[s2][i] + d[i][j] + d[j][t2] <= d2)
            {
                ans = min(ans,d[t1][i] + d[i][j] + d[j][s1] + d[s2][i] + d[j][t2]);
            }
            if(d[s1][i] + d[i][j] + d[j][t1] <= d1 && d[t2][i] + d[i][j] + d[j][s2] <= d2)
            {
                ans = min(ans,d[s1][i] + d[i][j] + d[j][t1] + d[t2][i] + d[j][s2]);
            }
            if(d[t1][i] + d[i][j] + d[j][s1] <= d1 && d[t2][i] + d[i][j] + d[j][s2] <= d2)
            {
                ans = min(ans,d[t1][i] + d[i][j] + d[j][s1] + d[t2][i] + d[j][s2]);
            }
        }
    }

//总路径数量减去最多的重复路径能完成条件的路径数量就是能删除的最多的路径
    printf ("%d\n",m - ans);

return 0;
}

Codeforces543BDestory Roads心得的更多相关文章

  1. 最小生成树:POJ1251-Jungle Roads(最小生成树的模板)

    POJ 1251 Jungle Roads >[poj原址:http://poj.org/problem?id=1251](http://poj.org/problem?id=1251) Des ...

  2. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  3. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  4. 我的MYSQL学习心得(二) 数据类型宽度

    我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  5. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  6. 我的MYSQL学习心得(四) 数据类型

    我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...

  7. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  8. 我的MYSQL学习心得(六) 函数

    我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  9. 我的MYSQL学习心得(七) 查询

    我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

随机推荐

  1. Uva11582

    最近各种破事忙死了 终于开始做题了 紫薯第10章第一题,come on 设g(i)=f(i) mod n,当二元组(g(i).g(i+1))出现重复时,整个序列就开始重复(这一话怎么也不懂,请大神解释 ...

  2. ReflectiveLoader分析(远程线程注入 PE修正)

    从github上下载了ReflectiverLoader认真学习了一下 在代码中得到一些心得和自己的想法,都按步骤写到了代码中,现在分享给大家,如有错,望大家指正 其中需要注入的dll和解析, 内存R ...

  3. ASP.NET没有魔法——ASP.NET MVC使用Area开发一个管理模块

    之前的My Blog提供了列表的展示和文章显示功能,但是所有数据仍然只能通过数据库录入,为了完成最初的角色“作者”的用例,本章将介绍如何使用“Area”实现My Blog的管理功能. 根据功能分离代码 ...

  4. Problem O

    Problem Description Before bridges were common, ferries were used to transport cars across rivers. R ...

  5. 理解Java包

    本质上,包是一个唯一命名的类的集合,将类集合到包里面的主要原因,是为了当在应用程序中使用预先编写的类时避免与类自身可能引起的明明冲突.用于包中的类名不会妨碍另一个包或程序中的类名,因为此时,包中的类名 ...

  6. JSP异常之org.apache.jasper.JasperException(转)

    According to TLD or attribute directive in tag file, attribute items does not accep t any expression ...

  7. 一场围绕着‘Deeping Learning’的高考

    Deep Learning的基本思想和方法 实际生活中,人们为了解决一个问题,如对象的分类(对象可是是文档.图像等),首先必须做的事情是如何来表达一个对象,即必须抽取一些特征来表示一个对象,如文本的处 ...

  8. AngularJS学习篇(八)

    AngularJS 服务(Service) 在 AngularJS 中,服务是一个函数或对象,可在你的 AngularJS 应用中使用. AngularJS 内建了30 多个服务. 为什么使用服务? ...

  9. js 作用域,作用域链,闭包

    什么是作用域? 作用域是一种规则,在代码编译阶段就确定了,规定了变量与函数的可被访问的范围.全局变量拥有全局作用域,局部变量则拥有局部作用域. js是一种没有块级作用域的语言(包括if.for等语句的 ...

  10. lvs学习笔记

    本人身为一个网工,最近一直在工作中学习linux的相关知识.前短时间通过自查资料学习了lvs的相关内容,摘录部分整理后和大家分享,内容较多,较琐碎,望见谅!!! LVS 从Linux内核版本2.6起, ...