CodeForces 543B. Destroying Roads 多源Dijkstra+暴力枚举

2023-11-07 05:09

本文主要是介绍CodeForces 543B. Destroying Roads 多源Dijkstra+暴力枚举,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 题目链接:

http://codeforces.com/problemset/problem/543/B

B. Destroying Roads

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 s1to 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 nm (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 aibi (1 ≤ ai, bi ≤ nai ≠ 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),让你去掉最多的边使得d(s1, t1) <= l1 && d(s2, t2) <= l2,若不能满足输出-1,反之输出可以去掉的最多边数。

使用Dijkstra,求出多源最短路径,然后暴力枚举重复的边,,,

求出最少的分别两个点的最短路径长度,因为单位长度为1,所以最后的边的数量减去长度,就是我们要摧毁的最大的边的数量

This is the code

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define pppp cout<<endl;
#define EPS 1e-8
#define LL long long
#define ULL unsigned long long     //1844674407370955161
#define INT_INF 0x3f3f3f3f      //1061109567
#define LL_INF 0x3f3f3f3f3f3f3f3f //4557430888798830399
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
const int dr[]={0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]={-1, 1, 0, 0, -1, 1, -1, 1};
const int maxn=3005;
struct HeapNode //Dijkstra算法用到的优先队列的节点
{int d,u;HeapNode(){ }HeapNode(int d,int u):d(d),u(u) {}bool operator < (const HeapNode &rhs)const{return d > rhs.d;//注意这个地方是大于号}
};
struct Edge     //边
{int from,to,dist;Edge(int f,int t,int d):from(f),to(t),dist(d) {}
};
struct Dijkstra
{int n,m;            //点数和边数,编号都从0开始vector<Edge> edges; //边列表vector<int> G[maxn];//每个节点出发的边编号(从0开始编号)bool done[maxn];    //是否已永久标号int d[maxn][maxn];  //d[s][t]的最近距离int p[maxn];        //p[i]为从起点s到i的最短路中的最后一条边的编号void init(int n){this->n=n;this->m=0;for(int i=0; i<=n; i++)G[i].clear();//清空邻接表edges.clear();  //清空边列表}void AddEdge(int from,int to,int dist){//如果是无向图,每条无向边调用两次AddEdgeedges.push_back(Edge(from,to,dist) );G[from].push_back(m++);}void dijkstra(int s)//求s到所有点的距离{priority_queue<HeapNode> Q;for(int i=0; i<=n; i++)d[s][i]=INT_INF;d[s][s]=0;memset(done,0,sizeof(done));Q.push(HeapNode(0,s) );while(!Q.empty()){HeapNode x=Q.top();Q.pop();int u=x.u;if(done[u])continue;done[u]= true;for(int i=0; i<G[u].size(); i++){Edge& e= edges[G[u][i]];if(d[s][e.to]> d[s][u]+e.dist){d[s][e.to] = d[s][u]+e.dist;p[e.to] = G[u][i];Q.push(HeapNode(d[s][e.to],e.to) );//这个地方要与HeapNode 里面的数据对应起来}}}}
} DJ;
inline int read()//输入外挂
{int ret=0, flag=0;char ch;if((ch=getchar())=='-')flag=1;else if(ch>='0'&&ch<='9')ret = ch - '0';while((ch=getchar())>='0'&&ch<='9')ret=ret*10+(ch-'0');return flag ? -ret : ret;
}
int main()
{int n=read();int m=read();DJ.init(n);for(int i=1;i<=m;++i){int u=read();int v=read();DJ.AddEdge(u,v,1);DJ.AddEdge(v,u,1);}int s1=read();int t1=read();int l1=read();int s2=read();int t2=read();int l2=read();for(int i=1;i<=n;++i)//DJ.dijkstra(i);if(DJ.d[s1][t1]>l1 || DJ.d[s2][t2]>l2)//最短路不能满足{cout<<"-1"<<endl;return 0;}int ans=DJ.d[s1][t1]+=DJ.d[s2][t2];for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(DJ.d[s1][i]+DJ.d[i][j]+DJ.d[j][t1]<=l1&&DJ.d[s2][i]+DJ.d[i][j]+DJ.d[j][t2]<=l2)//消除重复的路s1--t1 && s2--t2ans=min(ans,DJ.d[s1][i]+DJ.d[i][j]+DJ.d[j][t1]+DJ.d[s2][i]+DJ.d[j][t2]);if(DJ.d[s1][i]+DJ.d[i][j]+DJ.d[j][t1]<=l1&&DJ.d[t2][i]+DJ.d[i][j]+DJ.d[j][s2]<=l2)//s1--t1 && t2--s2ans=min(ans,DJ.d[s1][i]+DJ.d[i][j]+DJ.d[j][t1]+DJ.d[t2][i]+DJ.d[j][s2]);}}cout<<m-ans<<endl;//边数减去道路所需return 0;
}

 

这篇关于CodeForces 543B. Destroying Roads 多源Dijkstra+暴力枚举的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/361438

相关文章

Kotlin 枚举类使用举例

《Kotlin枚举类使用举例》枚举类(EnumClasses)是Kotlin中用于定义固定集合值的特殊类,它表示一组命名的常量,每个枚举常量都是该类的单例实例,接下来通过本文给大家介绍Kotl... 目录一、编程枚举类核心概念二、基础语法与特性1. 基本定义2. 带参数的枚举3. 实现接口4. 内置属性三、

MySQL实现多源复制的示例代码

《MySQL实现多源复制的示例代码》MySQL的多源复制允许一个从服务器从多个主服务器复制数据,这在需要将多个数据源汇聚到一个数据库实例时非常有用,下面就来详细的介绍一下,感兴趣的可以了解一下... 目录一、多源复制原理二、多源复制配置步骤2.1 主服务器配置Master1配置Master2配置2.2 从服

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1

C++11作用域枚举(Scoped Enums)的实现示例

《C++11作用域枚举(ScopedEnums)的实现示例》枚举类型是一种非常实用的工具,C++11标准引入了作用域枚举,也称为强类型枚举,本文主要介绍了C++11作用域枚举(ScopedEnums... 目录一、引言二、传统枚举类型的局限性2.1 命名空间污染2.2 整型提升问题2.3 类型转换问题三、C

Java 枚举的基本使用方法及实际使用场景

《Java枚举的基本使用方法及实际使用场景》枚举是Java中一种特殊的类,用于定义一组固定的常量,枚举类型提供了更好的类型安全性和可读性,适用于需要定义一组有限且固定的值的场景,本文给大家介绍Jav... 目录一、什么是枚举?二、枚举的基本使用方法定义枚举三、实际使用场景代替常量状态机四、更多用法1.实现接

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

C#实现获得某个枚举的所有名称

《C#实现获得某个枚举的所有名称》这篇文章主要为大家详细介绍了C#如何实现获得某个枚举的所有名称,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... C#中获得某个枚举的所有名称using System;using System.Collections.Generic;usi

Java 枚举的常用技巧汇总

《Java枚举的常用技巧汇总》在Java中,枚举类型是一种特殊的数据类型,允许定义一组固定的常量,默认情况下,toString方法返回枚举常量的名称,本文提供了一个完整的代码示例,展示了如何在Jav... 目录一、枚举的基本概念1. 什么是枚举?2. 基本枚举示例3. 枚举的优势二、枚举的高级用法1. 枚举