HDU-3416 Marriage Match IV(最短路+最大流)
来源:互联网 发布:微信提现赚钱软件大全 编辑:程序博客网 时间:2024/06/05 20:09
题意:
starvae在A城市想去B城市看他若干个女朋友,有m条有向边连着n个城市,但是他想走最短路,但每条路只能走一次,他想知道他能走多少条完全不同最短路去看他的女朋友们。
思路:
这题我们只能先把所有的最短路径求出来,然后把每条带权的路变成容量为1的网络边,然后求一个最大流即可。
怎么抽离出所有的最短路径呢,可以通过只求一次求从A到B的最短路,然后枚举每条边,判断是否满足dis[v] == dis[u]+1,然后建立网络图,虽然仍会有多余的边,但该流向B点的仍然会流向B点,不该流向B点的仍然不会流向B点。
也可以通过跑两次最短路,求出A点到所有点的最短路dis[0][i],和B点到所有点的最短路(反向边去求)dis[1][i],然后枚举每条边,判断是否满足dis[0][u]+dis[1][v]+w[u][v] == dis[0][B],然后建立网络图,这样所有的边恰好都是最短路径上的边了。(只能该方法处理出所有具体的最短路径)
也可以通过一个pre数组在dijistra算法上记录最短路径的走向,最后通过A点走过去也能得到所有的最短路径(也会有多余的)。
另外dinic会超时,SAP才可以过,以后乖乖用SAP吧...
代码1:
#include <algorithm> #include <iostream> #include <string.h> #include <cstdio> #include <queue> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 1005; const int maxm = 200005;struct node{int v, w, next;} edge[maxm]; int dis[maxn], pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn]; int t, n, m, no, up; int S, T;queue<int> q;struct node1{int v, w, next;bool operator<(const node1 k)const{return w > k.w;}} edge1[maxm];int no1, head1[maxn];int vis1[maxn], dis1[maxn];priority_queue<node1> q1;void init1(){no1 = 0;memset(head1, -1, sizeof head1);}inline void add1(int u, int v, int w){edge1[no1].v = v; edge1[no1].w = w;edge1[no1].next = head1[u]; head1[u] = no1++;}inline void add(int u, int v, int w) { edge[no].v = v; edge[no].w = w; edge[no].next = head[u]; head[u] = no++; edge[no].v = u; edge[no].w = 0; edge[no].next = head[v]; head[v] = no++; } inline void pre_init() { no = 0; memset(head, -1, sizeof head); } void init(int S, int T) { memset(gap, 0, sizeof gap); memset(dis, 0x3f, sizeof dis); for(int i = 0; i <= n; ++i) now[i] = head[i]; while(!q.empty()) q.pop(); dis[T] = 0; q.push(T); while(!q.empty()) { int tp = q.front(); q.pop(); ++gap[dis[tp]]; int k = head[tp]; while(k != -1) { if(dis[edge[k].v] == inf && edge[k^1].w) { dis[edge[k].v] = dis[tp]+1; q.push(edge[k].v); } k = edge[k].next; } } } int SAP(int S, int T) { up = n; int ans = 0, flow = inf, top = S; pre[S] = S; init(S, T); while(dis[S] < up) { if(top == T) { ans += flow; while(top != S) { edge[rec[top]].w -= flow; edge[rec[top]^1].w += flow; top = pre[top]; } flow = inf; } int k = now[top]; while(k != -1) { int v = edge[k].v; if(edge[k].w && dis[top] == dis[v]+1) { flow = min(flow, edge[k].w); pre[v] = top; rec[v] = k; now[top] = k; top = v; break; } k = edge[k].next; } if(k == -1) { int mind = up; if(--gap[dis[top]] == 0) break; int k = now[top] = head[top]; while(k != -1) { if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v]; k = edge[k].next; } ++gap[dis[top] = mind+1]; top = pre[top]; } } return ans; } void DJ(){while(!q1.empty()) q1.pop();memset(vis1, 0, sizeof vis1);memset(dis1, 0x3f, sizeof dis1);q1.push((node1){S, 0, -1});dis1[S] = 0;while(!q1.empty()){node1 tp = q1.top(); q1.pop();int u = tp.v;if(vis1[u]) continue;vis1[u] = 1;for(int k = head1[u]; k+1; k = edge1[k].next){int v = edge1[k].v;if(dis1[v] > dis1[u]+edge1[k].w){dis1[v] = dis1[u]+edge1[k].w;q1.push((node1){v, dis1[v], -1});}}}}void work(){DJ();for(int i = 1; i <= n; ++i)for(int k = head1[i]; k+1; k = edge1[k].next){int v = edge1[k].v;if(dis1[v] == dis1[i]+edge1[k].w)add(i, v, 1); } printf("%d\n", SAP(S, T)); }int main() { for(scanf("%d", &t); t--;){scanf("%d %d", &n, &m);init1(); pre_init(); for(int i = 1; i <= m; ++i){int u, v, w;scanf("%d %d %d", &u, &v, &w);if(u == v) continue;add1(u, v, w);}scanf("%d %d", &S, &T);work();} return 0; }
代码2:
#include <algorithm> #include <iostream> #include <string.h> #include <cstdio> #include <queue> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 1005; const int maxm = 200005;struct node{int v, w, next;} edge[maxm]; int dis[maxn], pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn]; int t, n, m, no, up; int S, T;queue<int> q;struct node1{int u, v, w, next;bool operator<(const node1 k)const{return w > k.w;}} edge1[2][maxm];int no1[2], head1[2][maxn];int vis1[2][maxn], dis1[2][maxn];priority_queue<node1> q1[2];void init1(){no1[0] = no1[1] = 0;memset(head1[0], -1, sizeof head1[0]);memset(head1[1], -1, sizeof head1[1]);}inline void add1(int key, int u, int v, int w){edge1[key][no1[key]].u = u; edge1[key][no1[key]].v = v; edge1[key][no1[key]].w = w;edge1[key][no1[key]].next = head1[key][u]; head1[key][u] = no1[key]++;}inline void add(int u, int v, int w) { edge[no].v = v; edge[no].w = w; edge[no].next = head[u]; head[u] = no++; edge[no].v = u; edge[no].w = 0; edge[no].next = head[v]; head[v] = no++; } inline void pre_init() { no = 0; memset(head, -1, sizeof head); } void init(int S, int T) { memset(gap, 0, sizeof gap); memset(dis, 0x3f, sizeof dis); for(int i = 0; i <= n; ++i) now[i] = head[i]; while(!q.empty()) q.pop(); dis[T] = 0; q.push(T); while(!q.empty()) { int tp = q.front(); q.pop(); ++gap[dis[tp]]; int k = head[tp]; while(k != -1) { if(dis[edge[k].v] == inf && edge[k^1].w) { dis[edge[k].v] = dis[tp]+1; q.push(edge[k].v); } k = edge[k].next; } } } int SAP(int S, int T) { up = n; int ans = 0, flow = inf, top = S; pre[S] = S; init(S, T); while(dis[S] < up) { if(top == T) { ans += flow; while(top != S) { edge[rec[top]].w -= flow; edge[rec[top]^1].w += flow; top = pre[top]; } flow = inf; } int k = now[top]; while(k != -1) { int v = edge[k].v; if(edge[k].w && dis[top] == dis[v]+1) { flow = min(flow, edge[k].w); pre[v] = top; rec[v] = k; now[top] = k; top = v; break; } k = edge[k].next; } if(k == -1) { int mind = up; if(--gap[dis[top]] == 0) break; int k = now[top] = head[top]; while(k != -1) { if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v]; k = edge[k].next; } ++gap[dis[top] = mind+1]; top = pre[top]; } } return ans; } void DJ(int key){while(!q1[key].empty()) q1[key].pop();memset(vis1[key], 0, sizeof vis1[key]);memset(dis1[key], 0x3f, sizeof dis1[key]);if(key == 0){q1[key].push((node1){-1, S, 0, -1});dis1[key][S] = 0;}else{q1[key].push((node1){-1, T, 0, -1});dis1[key][T] = 0;}while(!q1[key].empty()){node1 tp = q1[key].top(); q1[key].pop();int u = tp.v;if(vis1[key][u]) continue;vis1[key][u] = 1;for(int k = head1[key][u]; k+1; k = edge1[key][k].next){int v = edge1[key][k].v;if(dis1[key][v] > dis1[key][u]+edge1[key][k].w){dis1[key][v] = dis1[key][u]+edge1[key][k].w;q1[key].push((node1){-1, v, dis1[key][v], -1});}}}}void work(){DJ(0); DJ(1);int noo = no1[0];for(int i = 0; i < noo; ++i){int u = edge1[0][i].u, v = edge1[0][i].v;if(dis1[0][u]+dis1[1][v]+edge1[0][i].w == dis1[0][T])add(u, v, 1); } printf("%d\n", SAP(S, T)); }int main() { for(scanf("%d", &t); t--;){scanf("%d %d", &n, &m);init1(); pre_init(); for(int i = 1; i <= m; ++i){int u, v, w;scanf("%d %d %d", &u, &v, &w);if(u == v) continue;add1(0, u, v, w);add1(1, v, u, w); }scanf("%d %d", &S, &T);work();} return 0; }
代码3:
#include <unordered_set>#include <algorithm> #include <iostream> #include <string.h> #include <cstdio> #include <queue> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 1005; const int maxm = 200005;struct node{int v, w, next;} edge[maxm]; int dis[maxn], pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn]; int t, n, m, no, up; int S, T;queue<int> q;struct node1{int v, w, next;bool operator<(const node1 k)const{return w > k.w;}} edge1[maxm];int no1, head1[maxn];int vis1[maxn], dis1[maxn];unordered_set<int> G[maxn];priority_queue<node1> q1;queue<int> Q;void init1(){no1 = 0;memset(head1, -1, sizeof head1);}inline void add1(int u, int v, int w){edge1[no1].v = v; edge1[no1].w = w;edge1[no1].next = head1[u]; head1[u] = no1++;}inline void add(int u, int v, int w) { edge[no].v = v; edge[no].w = w; edge[no].next = head[u]; head[u] = no++; edge[no].v = u; edge[no].w = 0; edge[no].next = head[v]; head[v] = no++; } inline void pre_init() { no = 0; memset(head, -1, sizeof head); } void init(int S, int T) { memset(gap, 0, sizeof gap); memset(dis, 0x3f, sizeof dis); for(int i = 0; i <= n; ++i) now[i] = head[i]; while(!q.empty()) q.pop(); dis[T] = 0; q.push(T); while(!q.empty()) { int tp = q.front(); q.pop(); ++gap[dis[tp]]; int k = head[tp]; while(k != -1) { if(dis[edge[k].v] == inf && edge[k^1].w) { dis[edge[k].v] = dis[tp]+1; q.push(edge[k].v); } k = edge[k].next; } } } int SAP(int S, int T) { up = n; int ans = 0, flow = inf, top = S; pre[S] = S; init(S, T); while(dis[S] < up) { if(top == T) { ans += flow; while(top != S) { edge[rec[top]].w -= flow; edge[rec[top]^1].w += flow; top = pre[top]; } flow = inf; } int k = now[top]; while(k != -1) { int v = edge[k].v; if(edge[k].w && dis[top] == dis[v]+1) { flow = min(flow, edge[k].w); pre[v] = top; rec[v] = k; now[top] = k; top = v; break; } k = edge[k].next; } if(k == -1) { int mind = up; if(--gap[dis[top]] == 0) break; int k = now[top] = head[top]; while(k != -1) { if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v]; k = edge[k].next; } ++gap[dis[top] = mind+1]; top = pre[top]; } } return ans; } void DJ(){while(!q1.empty()) q1.pop();memset(vis1, 0, sizeof vis1);memset(dis1, 0x3f, sizeof dis1);q1.push((node1){S, 0, -1});dis1[S] = 0;while(!q1.empty()){node1 tp = q1.top(); q1.pop();int u = tp.v;if(vis1[u]) continue;vis1[u] = 1;for(int k = head1[u]; k+1; k = edge1[k].next){int v = edge1[k].v;if(dis1[v] > dis1[u]+edge1[k].w){dis1[v] = dis1[u]+edge1[k].w;G[v].clear();G[v].insert(u);q1.push((node1){v, dis1[v], -1});}else if(dis1[v] == dis1[u]+edge1[k].w) G[v].insert(u);}}}void work(){DJ();while(!Q.empty()) Q.pop();memset(vis1, 0, sizeof vis1);Q.push(S); vis1[S] = 1;while(!Q.empty()){int u = Q.front(); Q.pop();for(int k = head1[u]; k+1; k = edge1[k].next){int v = edge1[k].v;if(G[v].find(u) != G[v].end() && dis1[v] == dis1[u]+edge1[k].w){add(u, v, 1);if(!vis1[edge1[k].v])vis1[v] = 1, Q.push(v);}}}printf("%d\n", SAP(S, T)); }int main() { for(scanf("%d", &t); t--;){scanf("%d %d", &n, &m);init1(); pre_init(); for(int i = 1; i <= m; ++i){int u, v, w;scanf("%d %d %d", &u, &v, &w);if(u == v) continue;add1(u, v, w);}scanf("%d %d", &S, &T);work();} return 0; }
继续加油~
阅读全文
1 0
- hdu 3416 Marriage Match IV 【网络最大流+最短路】
- HDU 3416 Marriage Match IV(最短路+最大流)
- hdu 3416 Marriage Match IV (最短路+最大流)
- HDU 3416 Marriage Match IV(最短路+最大流)
- [HDU 3416]Marriage Match IV[最大流][最短路]
- HDU-3416 Marriage Match IV(最大流+最短路)
- HDU 3416 Marriage Match IV(最短路+最大流)
- HDU-3416 Marriage Match IV(最短路+最大流)
- hdoj 3416 Marriage Match IV 【最大流 + 最短路】
- HDOJ 3416 Marriage Match IV【最短路+最大流】
- HDU 3416 Marriage Match IV(中等,好题) [最大流]最短路+最大流
- Marriage Match IV (hdu 3416 网络流+spfa最短路)
- HDU 3416 Marriage Match IV(最短路,网络流)
- HDU 3416 Marriage Match IV(最短路+网络流之最大流)
- hdu 3416 Marriage Match IV 【图论-网络流-最短路+最大流(spfa + Dinic)】
- HDU 3416 —— Marriage Match IV(最短路+最大流)
- HDU — 3416 Marriage Match IV(最大流+最短路)
- HDU 3416 Marriage Match IV (最短路判断建边+最大流)
- 计蒜客-易张彪 字符串匹配KMP
- HTPPS和HTTP的概念和区别
- JavaScript-WebStorm中配置Github并将代码托管到Github
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'orderdetail.id' in 'fiel
- 第14章 多线程
- HDU-3416 Marriage Match IV(最短路+最大流)
- [bzoj1452][树状数组]Count
- 《统计学习方法》 Adaboost算法 Python实现
- 编程范式21
- LAMP环境搭建(CentOS7+Apache+Mariadb+PHP)
- 微信小程序蓝牙功能开发流程详解和思维导图--shewei
- BigDecimal用法详解
- ArduinoIDE开发ESP8266 远程控制继电器(物联网插座)之入门篇
- httpd的安装