Codeforces Round #302 (Div. 二) D. Destroying Roads(最短路)
Codeforces Round #302 (Div. 2) D. Destroying Roads(最短路)
n个结点,m条边的图(边权全为1),问最多能删掉多少条边使得s1到t1距离不超过l1,s2到t2距离不超过l2。
思路:其实题目的意思也就是说最少需要多少条边使得s1到t1距离不超过l1且s2到t2距离不超过l2.如果需要的边没有相交那么显然是两个最短路上边,如果相交那么应该是相交部分的最短路和相交的两个端点到其他四个点的最短路,所以我们可以先预处理出任意两点间的最短路,然后枚举相交部分的两个端点,最后用总边数减去需要的边数就是答案
#include <bits/stdc++.h> #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it) using namespace std; typedef long long ll; const int inf = 1e7; const int maxn = 3000 + 5; int n,m; int d[maxn][maxn]; vector<int> G[maxn]; void AddEdge(int u,int v) { G[u].push_back(v); G[v].push_back(u); } void bfs(int cur) { memset(d[cur],0,sizeof d[cur]); queue<int>q; q.push(cur); while(!q.empty()) { int u = q.front(); q.pop(); foreach(it,G[u])if(!d[cur][*it]){ d[cur][*it] = d[cur][u] + 1; q.push(*it); } } for(int i = 1; i <= n; i++) if(!d[cur][i]) d[cur][i] = inf; d[cur][cur] = 0; } int main() { while(~scanf("%d%d",&n,&m)) { for(int i = 1; i <= n; i++)G[i].clear(); for(int i = 1; i <= m; i++) { int u,v;scanf("%d%d",&u,&v); AddEdge(u,v); } for(int i = 1; i <= n; i++)bfs(i); int s1,t1,l1,s2,t2,l2; scanf("%d%d%d%d%d%d",&s1,&t1,&l1,&s2,&t2,&l2); if(d[s1][t1]>l1||d[s2][t2]>l2) { puts("-1"); continue; } int res = d[s1][t1]+d[s2][t2]; for(int i = 1; i <= n; i++) { for(int j = i; j <= n; j++) { int w1 = min(d[s1][i]+d[i][j]+d[j][t1], d[s1][j]+d[j][i]+d[i][t1]); int w2 = min(d[s2][i]+d[i][j]+d[j][t2], d[s2][j]+d[j][i]+d[i][t2]); if(w1>l1||w2>l2)continue; res = min(res,w1+w2-d[i][j]); } } printf("%d\n", m - res); } return 0; }