[Codeforces 507E] Breaking Good
[题目链接]
https://codeforces.com/contest/507/problem/E
[算法]
首先BFS求出1到其余点的最短路 , N到其余点的最短路,记为distA[]和distB[]
显然 , 我们只需最大化求出的最短路上没有被破坏的边即可 , 不妨用f[i]表示现在在城市i , distA[i] + distB[i] = distA[N] , 最多还能经过几条没有被破坏的边
记忆化搜索即可
时间复杂度 : O(N)
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 10; const int inf = 1e9; struct edge { int to , state , id , nxt; } e[MAXN << 1]; struct info { int u , v , ns; } res[MAXN]; int n , m , tot; int u[MAXN],v[MAXN],state[MAXN],head[MAXN],dista[MAXN],distb[MAXN],f[MAXN]; pair<int,int> nxt[MAXN]; bool visited[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int u,int v,int s,int id) { tot++; e[tot] = (edge){v,s,id,head[u]}; head[u] = tot; } inline void bfs1(int s) { queue< int > q; dista[s] = 0; visited[s] = true; q.push(s); while (!q.empty()) { int cur = q.front(); q.pop(); for (int i = head[cur]; i; i = e[i].nxt) { int v = e[i].to; if (!visited[v]) { visited[v] = true; dista[v] = dista[cur] + 1; q.push(v); } } } } inline void bfs2(int s) { queue< int > q; distb[s] = 0; visited[s] = true; q.push(s); while (!q.empty()) { int cur = q.front(); q.pop(); for (int i = head[cur]; i; i = e[i].nxt) { int v = e[i].to; if (!visited[v]) { visited[v] = true; distb[v] = distb[cur] + 1; q.push(v); } } } } inline int dp(int u) { if (u == n) return f[u] = 0; if (f[u] != -1) return f[u]; f[u] = -inf; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to , st = e[i].state , id = e[i].id , value; if (dista[u] + distb[v] + 1 != dista[n]) continue; if (st == 1) { value = dp(v) + 1; if (value > f[u]) { f[u] = value; nxt[u] = make_pair(v,id); } } else { value = dp(v); if (value > f[u]) { f[u] = value; nxt[u] = make_pair(v,id); } } } return f[u]; } inline void getpath(vector<int> &a) { int now = 1; while (nxt[now].first) { a.push_back(nxt[now].second); now = nxt[now].first; } } int main() { read(n); read(m); for (int i = 1; i <= m; i++) { read(u[i]); read(v[i]); read(state[i]); addedge(u[i],v[i],state[i],i); addedge(v[i],u[i],state[i],i); } memset(visited,false,sizeof(visited)); bfs1(1); memset(visited,false,sizeof(visited)); bfs2(n); memset(f,255,sizeof(f)); dp(1); vector<int> path; getpath(path); int len = 0; memset(visited,false,sizeof(visited)); for (unsigned i = 0; i < path.size(); i++) { visited[path[i]] = true; if (state[path[i]] == 0) res[++len] = (info){u[path[i]],v[path[i]],1}; } for (int i = 1; i <= m; i++) { if (!visited[i] && state[i]) res[++len] = (info){u[i],v[i],0}; } printf("%d\n",len); for (int i = 1; i <= len; i++) printf("%d %d %d\n",res[i].u,res[i].v,res[i].ns); return 0; }