AtCoder Beginner Contest 218

[ABC218E] Destruction

题意翻译

给一个无向图,让你从中选出几个边,要求选出的边权总和最大并且剩下的图要是一个连通图,输出最大的边权。


 

贪心的想剩下来的图一定是一个树结构,那么要满足去掉的边权和大,就可以想到最小生成树,用总边权减去最小生成树就是答案


 

[ABC218F] Blocked Road

题面翻译

给定一张 n 个点,m 条边的有向图,每条边的边权均为 1。请对于每一个$i\in [1,m]$求出从点 1n 的不经过第 i 条边的最短路长度。


 

最朴素的做法是枚举每条边被删去后进行$\space bfs\space$复杂度就是$\space O(m \times \space (n + \space m))$

对于稠密图$\space m\space = n ^ 2$,显然这样子复杂度是$\space O(n^4)$

最短路上边最多$\space n - 1\space $条,也就是说我们只需要关心这条最短路上的边,删去其他边并不会改变最短路长度

所以这样子复杂度是$\space O(n \times \space (n + \space m))$,对于稠密图复杂度是$\space O(n^3)$

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;

const int N = 200100;
const int inf = INT_MAX / 2;

int n, m, vis[N], dist[N], pre[N];
vector
<int> edge[N];
array
<int, 2> e[N];

int bfs(int not_go){
queue
<int> q; q.push(1);
for(int i = 1; i <= n; i++) dist[i] = inf, vis[i] = 0;
dist[
1] = 0, vis[1] = 1;
while(!q.empty()) {
auto x
= q.front(); q.pop();
for(auto y : edge[x]) {
if(e[not_go] == (array<int, 2>){x, y}) continue;
if(dist[y] > dist[x] + 1) {
dist[y]
= dist[x] + 1;
q.push(y);
if(!not_go) pre[y] = x;
}
}
}
if(dist[n] >= inf) return -1;
return dist[n];
}

int main(){
ios::sync_with_stdio(
false), cin.tie(0), cout.tie(0);
cin
>> n >> m;
for(int i = 1; i <= m; i++) {
int x, y; cin >> x >> y;
edge[x].push_back(y);
e[i]
= {x, y};
}
int ans = bfs(0), now = n;
map
<pair<int, int>, int> mp;
while(now != 1) {
if(!pre[now]) break;
int x = pre[now];
mp[{x, now}]
= 1;
now
= pre[now];
}
if(now != 1) ans = -1;
for(int i = 1; i <= m; i++) {
if(!mp[{e[i][0], e[i][1]}]) cout << ans << endl;
else cout << bfs(i) << endl;
}
return 0;
}

View Code

 


 

 

posted @ 2023-09-13 16:58  zhujio  阅读(18)  评论(0编辑  收藏  举报