标签:bool pair long vector lin scan 其他 main pre
思路:属于最短路径上的边应该满足:dis_A[u] + dis_B[v] + w == dis_A[B],dis_A是出发点到其他点的距离,dis_B是终点到其他点的距离,u,v是边的两个端点,w是权值。题目说每条边只能用一次,我们可以用最大流算法来求最短路径有几条。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <queue> 5 #include <vector> 6 7 using namespace std; 8 9 #define ll long long 10 #define pb push_back 11 #define fi first 12 #define se second 13 14 const int N = 1010; 15 const int M = 1e5; 16 const int INF = 1e9; 17 struct node{ 18 int x, d; 19 bool friend operator<(const node& a, const node& b){ 20 return a.d > b.d; 21 } 22 }; 23 struct edge{ 24 int to, nxt, flow; 25 }e[M << 1]; 26 vector<pair<int, int> > E[2][N]; 27 int dis[2][N]; 28 priority_queue<node > que; //最短路 29 queue<int > Q;//网络流分层 30 int d[N];//层级 31 int n, m, A, B; 32 int head[N], cur[N], vis[N], id[N]; //链式,当前弧优化,...,编号记录 33 int tot, cnt; 34 35 void dijkstra(int now, int pos) 36 { 37 for(int i = 0; i <= n; ++i) dis[pos][i] = INF; 38 while(!que.empty()) que.pop(); 39 dis[pos][now] = 0; 40 que.push({now, 0}); 41 42 while(!que.empty()){ 43 int u = que.top().x; 44 que.pop(); 45 46 for(auto e : E[pos][u]){ 47 int v = e.fi; 48 int w = e.se; 49 50 if(dis[pos][v] > dis[pos][u] + w){ 51 dis[pos][v] = dis[pos][u] + w; 52 que.push({v, dis[pos][v]}); 53 } 54 } 55 } 56 57 } 58 59 inline void add(int u, int v) 60 { 61 e[tot].to = v; e[tot].flow = 1; 62 e[tot].nxt = head[u]; head[u] = tot++; 63 e[tot].to = u; e[tot].flow = 0; 64 e[tot].nxt = head[v]; head[v] = tot++; 65 } 66 67 void build() 68 { 69 for(int i = 0; i <= n; ++i) head[i] = -1; tot = 0; 70 for(int x = 1; x <= n; ++x){ 71 for(auto e : E[0][x]){ 72 int y = e.fi; 73 int w = e.se; 74 if(dis[0][x] + dis[1][y] + w == dis[0][B] || dis[0][y] + dis[1][x] + w == dis[0][B]){ 75 if(!vis[x]) id[cnt++] = x, vis[x] = 1; 76 if(!vis[y]) id[cnt++] = y, vis[y] = 1; 77 add(x, y); 78 } 79 } 80 } 81 } 82 83 bool bfs() 84 { 85 while(!Q.empty()) que.pop(); 86 for(int i = 0; i < cnt; ++i) { 87 d[id[i]] = 0; 88 } 89 d[A] = 1; 90 Q.push(A); 91 92 while(!Q.empty()){ 93 int now = Q.front(); 94 95 Q.pop(); 96 97 for(int o = head[now]; ~o; o = e[o].nxt){ 98 int to = e[o].to; 99 int flow = e[o].flow; 100 101 if(flow && !d[to]){ 102 d[to] = d[now] + 1; 103 Q.push(to); 104 } 105 } 106 } 107 108 if(!d[B]) return false; 109 else return true; 110 } 111 112 int dfs(int now, int pre_flow){ 113 if(now == B) return pre_flow; 114 int sum = 0; 115 for(int& o = cur[now]; ~o; o = e[o].nxt){ 116 int to = e[o].to; 117 int flow = e[o].flow; 118 119 if(flow && d[to] == d[now] + 1){ 120 int tmp = dfs(to, min(pre_flow - sum, flow)); 121 if(tmp == 0) continue; 122 e[o].flow -= tmp; 123 e[o ^ 1].flow += tmp; 124 sum += tmp; 125 if(sum == pre_flow) return sum; 126 } 127 } 128 return sum; 129 } 130 131 void dinic() 132 { 133 int mf = 0; 134 while(bfs()){ 135 for(int i = 0; i < cnt; ++i) cur[id[i]] = head[id[i]]; 136 mf += dfs(A, INF); 137 } 138 139 printf("%d\n", mf); 140 } 141 142 void init(){ 143 for(int i = 0; i <= n; ++i){ 144 E[0][i].clear(); 145 E[1][i].clear(); 146 } 147 for(int i = 0; i < cnt; ++i) vis[id[i]] = 0; 148 cnt = 0; 149 } 150 151 void solve() 152 { 153 int T; 154 scanf("%d", &T); 155 156 while(T--){ 157 scanf("%d%d", &n, &m); 158 159 init(); 160 161 int u, v, w; 162 for(int i = 0; i < m; ++i){ 163 scanf("%d%d%d", &u, &v, &w); 164 if(u == v) continue; 165 E[0][u].pb(make_pair(v, w)); 166 E[1][v].pb(make_pair(u, w)); 167 } 168 scanf("%d%d", &A, &B); 169 dijkstra(A, 0); 170 dijkstra(B, 1); 171 172 build(); 173 dinic(); 174 } 175 } 176 177 int main() 178 { 179 180 solve(); 181 182 return 0; 183 }
标签:bool pair long vector lin scan 其他 main pre
原文地址:https://www.cnblogs.com/SSummerZzz/p/13220282.html