题意:
给定一个无向带权图G(n, m),一个人要沿着最短路从1走到n,现在可以任意从图上删边。求,最少删多少边可以使之无法到达终点 和 最多删多少边其仍可以到达终点
想法:
比赛时的想法:直接跑最小费用最大流,spfa的时候维护一个最短路的值(min_dist),如果当前求得增广路径的最短路的值大于min_dist,肯定后面的最短路就都大于min_dist了,此时就已经求出最大流即第一问的答案了。在求增广路径的过程中维护所有最短路的最小边数,总边数减去最小边数就是即为第二问的答案。(没有觉得思路有什么问题,赛后对着数据,总是有两组跑的特别慢并且答案也是错的)。
后来按照标程写了一个,先一遍spfa求出所有最短录,并且得到最少边数。然后遍历所有边将最短路建图(这个图是根据最短路中dist值建的有向图),在新图上跑一遍最大流。结果两组数据还是过不去。
现记下来,回头补上。
武大训练第10场又挂了这个题,比赛时候补上了。
这是题解说的先最短路,重新建图再跑网络流的做法
2015-9-12 补充,费用流没法做,因为在求增广路的时候会改变图中最短路上边的数量。对网络流还是不够熟悉
1 #include <bits/stdc++.h> 2 3 const int MAXN = 2000+100; 4 const int MAXM = 200000+100; 5 const int INF = 0x3f3f3f3f; 6 7 typedef std::pair<int, int> pii; 8 9 struct Edge{ 10 int u, v, cap, next; 11 Edge(){} 12 Edge(int u, int v, int cap, int next) 13 { 14 this->u = u; 15 this->v = v; 16 this->cap = cap; 17 this->next = next; 18 } 19 }edge[MAXM]; 20 int head[MAXN]; 21 int tot; 22 std::vector<pii> ve[MAXN]; 23 int dep[MAXN]; 24 int n, m; 25 int dist[MAXN]; 26 bool vis[MAXN]; 27 int road[MAXN]; 28 29 void addEdge(int u, int v, int cap) 30 { 31 edge[++tot] = Edge(u, v, cap, head[u]); 32 head[u] = tot; 33 } 34 35 int dfs(int u, int sink, int min_flow) 36 { 37 if (u == sink) { 38 return min_flow; 39 } 40 int res = 0; 41 for (int i = head[u]; i > 0 && min_flow > 0; i = edge[i].next) { 42 if (dep[edge[i].v] == dep[u] + 1) { 43 int dd = dfs(edge[i].v, sink, std::min(min_flow, edge[i].cap)); 44 edge[i].cap -= dd; 45 edge[i^1].cap += dd; 46 res += dd; 47 min_flow -= dd; 48 } 49 } 50 return res; 51 } 52 53 void bfs(int src, int sink) 54 { 55 memset(dep, 0, sizeof dep); 56 std::queue<int> que; 57 que.push(src); 58 dep[src] = 1; 59 while (que.empty() == false) { 60 int u = que.front(); 61 que.pop(); 62 for (int i = head[u]; i > 0; i = edge[i].next) { 63 int v = edge[i].v; 64 int cap = edge[i].cap; 65 if (dep[v] == 0 && cap > 0) { 66 dep[v] = dep[u] + 1; 67 if (v == n) { 68 return; 69 } 70 que.push(v); 71 } 72 } 73 } 74 } 75 76 int dinic(int src, int sink) 77 { 78 int res = 0; 79 while (true) { 80 bfs(src, sink); 81 if (dep[sink] == 0) { 82 return res; 83 } 84 res += dfs(src, sink, INF); 85 } 86 } 87 88 void init() 89 { 90 tot = 1; 91 memset(head, 0, sizeof head); 92 for (int i = 1; i <= n; ++ i) { 93 ve[i].clear(); 94 } 95 } 96 97 int main() 98 { 99 while (~scanf("%d%d" , &n, &m)) { 100 init(); 101 for (int i = 1; i <= m; ++ i) { 102 int u, v, cost; 103 scanf("%d%d%d", &u, &v, &cost); 104 if (u == v) 105 continue; 106 ve[u].push_back(std::make_pair(v, cost)); 107 ve[v].push_back(std::make_pair(u, cost)); 108 } 109 memset(vis, false, sizeof vis); 110 for (int i = 1; i <= n; ++ i) { 111 dist[i] = INF; 112 road[i] = INF; 113 } 114 dist[1] = 0; 115 road[1] = 0; 116 std::queue<int> que; 117 que.push(1); 118 vis[1] = true; 119 while (que.empty() == false) { 120 int u = que.front(); 121 que.pop(); 122 vis[u] = false; 123 for (int i = 0; i < (int)ve[u].size(); ++ i) { 124 int v = ve[u][i].first; 125 if (dist[v] > dist[u] + ve[u][i].second) { 126 dist[v] = dist[u] + ve[u][i].second; 127 if (vis[v] == false ) { 128 vis[v] = true; 129 que.push(v); 130 } 131 } 132 } 133 } 134 135 que.push(1); 136 memset(vis, false, sizeof vis); 137 memset(road, 0x3f3f3f3f, sizeof road); 138 road[1] = 0; 139 vis[1] = true; 140 while (que.empty() == false) { 141 int u = que.front(); 142 que.pop(); 143 for (int i = 0; i < (int)ve[u].size(); ++ i) { 144 int v = ve[u][i].first; 145 int w = ve[u][i].second; 146 if (dist[v] == dist[u] + w) { 147 addEdge(u, v, 1); 148 addEdge(v, u, 0); 149 150 vis[v] = true; 151 que.push(v); 152 road[v] = std::min(road[v], road[u] + 1); 153 } 154 } 155 } 156 int res2 = m - road[n]; 157 int res1 = dinic(1, n); 158 printf("%d %d ", res1, res2); 159 } 160 }