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;
}
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;
}
相关文章推荐
- ubuntu 16.04.1 u盘安装问题
- mysql的启动与连接
- servlet转发·重定向·包含常见问题
- locate command not found
- locate command not found
- hdu2119 Matrix
- 解决php向mysql数据库插入数据乱码问题
- The Production installation of DataPusher for Ckan2.5.2 on CentOS6.8
- 第二章 物理层(笔记)
- Android adt v22.6.2 自动创建 appcompat_v7 解决方法,最低版本2.2也不会出现
- 脱离文档流
- 为什么要使用反射
- Linux值得拥有的性能监控工具
- Linux中的shell
- c语言函数指针的作用
- Interpolator定义动画变化率 如微博发动态
- 深度学习在搜狗无线搜索广告中的应用
- lua 语法
- cordova编译报错:Execution failed for task ':processDebugResources'
- MySQL优化之二--存储引擎