题解 CF543B 【Destroying Roads】

ShineEternal

2019-07-21 19:32:21

Solution

> https://www.cnblogs.com/ShineEternal/p/11222368.html 看到没有题解就贡献一波呗 题解通过率:114/164 # 分析: 这题其实就是想让我们求一个图中两条最短路的最短(好把更多的边删掉)。 我们先考虑一条最短路,~~别问我我怎么会的~~显然,就是s和t跑个最短路再用n-就行。 然后就是两条喽!~~这不就是做两次吗,我太巨了!~~ 这当然是可以的 ## ——不过只是一种情况 考虑到我们的两条路径可能会有重合,我们只好**枚举重合最短路的左右端点**,将路径分为5段(6段?)来处理。 然后问题基本就解决了,最开始把两两点之间预处理出最短路,这里要注意bfs即可~~别告诉我你要用Floyd~~ 最后的答案如果比m大就-1了。 l1,l2的限制条件不要忘了判断鸭! # 代码: ```cpp #include<cstdio> #include<queue> #include<iostream> #include<vector> #include<cstring> using namespace std; int d[3005][3005]; int vis[3005]; vector<int>e[3005]; void bfs(int s) { memset(vis,0,sizeof(vis)); queue<int>q; q.push(s); //vis[s]=1; d[s][s]=0; while(!q.empty()) { int x=q.front();q.pop(); if(vis[x])continue; vis[x]=1; for(int i=0;i<e[x].size();i++) { int y=e[x][i]; if(d[s][y]==-1) { d[s][y]=d[s][x]+1; //printf("%d\n",d[s][y]); q.push(y); } } } } int main() { int n,m; scanf("%d%d",&n,&m); memset(d,-1,sizeof(d)); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } int s1,t1,l1,s2,t2,l2; scanf("%d%d%d",&s1,&t1,&l1); scanf("%d%d%d",&s2,&t2,&l2); for(int i=1;i<=n;i++) { // printf("qaq\n"); bfs(i); } /*for(int i=0;i<=n;i++) { for(int j=0;j<=n;j++) { printf("%d ",d[i][j]); } printf("\n"); }*/ int ans=999999999; 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)continue; if(d[s2][i]+d[i][j]+d[j][t2]>l2)continue; ans=min(ans,d[s1][i]+d[i][j]+d[j][t1]+d[s2][i]+d[i][j]+d[j][t2]-d[i][j]); } } if(d[s1][t1]<=l1&&d[s2][t2]<=l2) { ans=min(ans,d[s1][t1]+d[s2][t2]); } swap(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)continue; if(d[s2][i]+d[i][j]+d[j][t2]>l2)continue; ans=min(ans,d[s1][i]+d[i][j]+d[j][t1]+d[s2][i]+d[i][j]+d[j][t2]-d[i][j]); } } if(d[s1][t1]<=l1&&d[s2][t2]<=l2) { ans=min(ans,d[s1][t1]+d[s2][t2]); } if(ans>m)printf("-1\n"); else printf("%d\n",m-ans); return 0; } ```