Codeforces543 B. Destroying Roads
Posted qixingzhi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces543 B. Destroying Roads相关的知识,希望对你有一定的参考价值。
传送门:>Here<
题意:给出一张无向图(边权为1),并给出两对起点和终点以及距离:s1,t1,l1; s2,t2,l2; 要求删除尽量多的边,使得dis(s1,t1)<=l1, dis(s2,r2)<=l2
解题思路
首先我们会发现,由于边权都为1,删去一些边,某两点间的最短路肯定会随着删的边越来越多而越来越长(捷径被删了)
因此我们会发现,要让边删的尽量多,最好最后只剩下最短路,其它边都剩下。换句话说,如果两条最短路不相交,那么最后只会剩下孤零零的两条链
于是我们会发现,我们可以初步得到一个答案:$M - d(s1,t1) - d(s2,t2)$
但这有可能不是最优的答案——两条最短路有可能有重叠。重叠的部分越长,答案就会越大也就是更优。并且很容易证明,重叠肯定只有连续的一段,而不会有间断的两断——因为如果需要有两断的话肯定不如连起来变为一段来的优。所以可以$O(n^2)$枚举重叠部分,验证一下就好了
Code
用SPFA预处理出任意两点间的距离,注意数组要开$N*N$
教训:当出现莫名其妙的错误的时候,首先检查数组有没有开错——例如,int开成bool,开得太小等等
/*By QiXingzhi*/ #include <cstdio> #include <queue> #include <cstring> #include <algorithm> #define r read() #define Max(a,b) (((a)>(b)) ? (a) : (b)) #define Min(a,b) (((a)<(b)) ? (a) : (b)) using namespace std; typedef long long ll; const int MAXN = 3010; const int MAXM = 5000010; const int INF = 1061109567; inline int read(){ int x = 0; int w = 1; register int c = getchar(); while(c ^ ‘-‘ && (c < ‘0‘ || c > ‘9‘)) c = getchar(); if(c == ‘-‘) w = -1, c = getchar(); while(c >= ‘0‘ && c <= ‘9‘) x = (x << 3) +(x << 1) + c - ‘0‘, c = getchar(); return x * w; } int N,M,x,y,s1,t1,l1,s2,t2,l2,top,sp1; int first[MAXM*2],nxt[MAXM*2],to[MAXM*2],num_edge; int d[MAXN][MAXN],inQ[MAXN],pre[MAXN],ans[MAXN],tmp[MAXN]; queue <int> q; inline void add(int u, int v){ to[++num_edge] = v; nxt[num_edge] = first[u]; first[u] = num_edge; } inline void SPFA(int s, int c){ for(int i = 0; i <= N; ++i) d[i][c] = INF; memset(inQ, 0, sizeof(inQ)); d[s][c] = 0; q.push(s); int u,v; while(!q.empty()){ u = q.front();q.pop(); inQ[u] = 0; for(int i = first[u]; i; i = nxt[i]){ v = to[i]; if(d[u][c] + 1 < d[v][c]){ d[v][c] = d[u][c] + 1; if(!inQ[v]){ inQ[v] = 1; q.push(v); } } } } } int main(){ // freopen(".in","r",stdin); N=r,M=r; for(int i = 1; i <= M; ++i){ x=r,y=r; add(x, y), add(y, x); } s1=r,t1=r,l1=r; s2=r,t2=r,l2=r; for(int i = 1; i <= N; ++i){ SPFA(i, i); } if(d[s1][t1] > l1 || d[s2][t2] > l2){ printf("-1"); return 0; } int Ans = M - d[s1][t1] - d[s2][t2]; if(Ans < 0) Ans = 0; for(int i = 1; i <= N; ++i){ for(int j = 1; j <= N; ++j){ if(i == j) continue; if(d[s1][i] + d[j][t1] + d[i][j] <= l1){ if(d[s2][i] + d[j][t2] + d[i][j] <= l2){ Ans = Max(Ans, M - (d[s1][i]+d[i][j]+d[j][t1]+d[s2][i]+d[j][t2])); } if(d[s2][j] + d[i][t2] + d[i][j] <= l2){ Ans = Max(Ans, M - (d[s1][i]+d[i][j]+d[j][t1]+d[s2][j]+d[i][t2])); } } if(d[s1][j] + d[i][t1] + d[i][j] <= l1){ if(d[s2][i] + d[j][t2] + d[i][j] <= l2){ Ans = Max(Ans, M - (d[s1][j]+d[i][j]+d[i][t1]+d[s2][i]+d[j][t2])); } if(d[s2][j] + d[i][t2] + d[i][j] <= l2){ Ans = Max(Ans, M - (d[s1][j]+d[i][j]+d[i][t1]+d[s2][j]+d[i][t2])); } } } } printf("%d", Ans); return 0; }
以上是关于Codeforces543 B. Destroying Roads的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces#543 div2 B. Mike and Children(暴力?)
codeforces 543B Destroying Roads