HDU 3416 Marriage Match IV (SPFA+最大流)
来源:互联网 发布:java面试问题 编辑:程序博客网 时间:2024/05/16 12:13
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416
题意:
每条边最多只走一次,统计最短路径条数。
解题思路:
看到题目,限制了走的次数,想到了网络流,容量为1,即为限制一次,又统计最短路径条数,想到最小费用最大流,在增流时判断现在增流的花费是否大于最短路径,也就是第一次增流的花费,如果大于,结束,如果不大于,继续。结果TLE
看题解后,很强大。
既然只统计最短路径条数,那么只有在最短路径的边是有用的,如果能统计出起始点到所有点的最短距离dist1,所有点到终止点的最短距离dist2,任意一条边,看这条边的起始点dist1加上边权加上终止点的dist2,如果等于最短路径,则在最短路径中,是有效的,如果不满足,则不再最短路径中,也就没有用了。
找到由最短路径构成的图,跑一遍最大流,就得到答案。
完成上述这的过程就需要dist1和dist2,也就是正图以起始点为起始点跑最短路,重新建逆图,逆图以终止点为起始点跑一遍最短路,就得到dist1和dist2.然后重新建图。这个就很强势了,让我知道了链式前向星怎么建逆图。之所以逆图表示所有点到终止点的距离,可以这样理解,逆图中终止点指向的边都是原本指向终止点的,那么,在逆图中跑的最短路,就是其他点跑向终止点的最短路。
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;typedef pair<int, int> P;const int N = 1010;const int M = 100005;const int INF = 1e9;struct edge { int to, next; int dist, c, f;}graph[M<<1];int totlen;int head[N];int n, m;int a[M], b[M], c[M];int s, t;// Dinicint level[N];int cur[N];bool dinic_bfs() { memset(level, 0, sizeof(level)); queue<int> que; que.push(s); level[s] = 1; while(!que.empty()) { int u = que.front(); que.pop(); for(int i = head[u]; i != -1; i = graph[i].next) { int v = graph[i].to; if(!level[v] && graph[i].c > graph[i].f) { level[v] = level[u]+1; que.push(v); } } } return level[t] != 0;}int dinic_dfs(int u, int cpflow) { // cpflow: can pass flow 到达u点最大能通过的流量 if(u == t) return cpflow; // 到达汇点 int addflow = 0; // u 点到其他点 最多能增广的流量, 最多不能超过cpflow,由前面的边限制 for(int& i = cur[u]; i != -1 && addflow < cpflow; i = graph[i].next){ int v = graph[i].to; if(level[u]+1 == level[v] && graph[i].c > graph[i].f) { // 这一条路上增广的流量 int tmpadd = dinic_dfs(v, min(cpflow-addflow, graph[i].c-graph[i].f)); if(tmpadd > 0) { graph[i].f += tmpadd; // 正向通过的流量加 graph[i^1].f -= tmpadd; // 反向的流量就得减 return tmpadd; } } } return 0; // 返回这个点都汇点能增广的流量}int dinic() { int maxflow = 0; int tmpflow = 0; while(dinic_bfs()) { memcpy(cur, head, sizeof(head)); while((tmpflow = dinic_dfs(s, INF)) > 0) maxflow += tmpflow; } return maxflow;}// Dijkstrabool visit[N];int dist1[N], dist2[N];priority_queue<P, vector<P>, greater<P> > que;void dijkstra(int s, int* dist) { for(int i = 0; i <= n; i++) dist[i] = INF; for(int i = 0; i <= n; i++) visit[i] = 0; while(!que.empty()) que.pop(); dist[s] = 0; que.push(P(0, s)); while(!que.empty()) { P cur = que.top(); que.pop(); int u = cur.second; if(visit[u]) continue; visit[u] = true; for(int i = head[u]; i != -1; i = graph[i].next) if(!visit[graph[i].to]) { int v = graph[i].to; if(dist[v] > dist[u]+graph[i].dist) { dist[v] = dist[u]+graph[i].dist; que.push(P(dist[v], v)); } } }}void addEdge(int u, int v, int c, int dist) { if(u == v) return; // 正向边 graph[totlen].to = v; graph[totlen].next = head[u]; graph[totlen].dist = dist; graph[totlen].c = c; graph[totlen].f = 0; head[u] = totlen++; // 添加反向边 graph[totlen].to = u; graph[totlen].next = head[v]; graph[totlen].dist = INF; graph[totlen].c = 0; graph[totlen].f = 0; head[v] = totlen++; // 正向边下标通过异或就得到反向边下标, 2 ^ 1 == 3 ; 3 ^ 1 == 2}void init() { for(int i = 0; i <= n; i++) head[i] = -1; totlen = 0;}int main() { int _; scanf("%d", &_); while(_--) { scanf("%d%d", &n, &m); for(int i = 0; i < m; i++){ int u, v, w; scanf("%d%d%d", &a[i], &b[i], &c[i]); } scanf("%d%d", &s, &t); init(); for(int i = 0; i < m; i++) addEdge(a[i], b[i], 1, c[i]); dijkstra(s, dist1); init(); for(int i = 0; i < m; i++) addEdge(b[i], a[i], 1, c[i]); dijkstra(t, dist2); init(); for(int i = 0; i < m; i++) { int u = a[i]; int v = b[i]; int w = c[i]; if(dist1[u]+dist2[v]+w == dist1[t]) { addEdge(u, v, 1, w); } } int ans = dinic(); printf("%d\n", ans); } return 0;}
阅读全文
0 0
- 【HDU】 3416 Marriage Match IV(最大流+SPFA)
- HDU 3416 Marriage Match IV (SPFA+最大流)
- HDU 3416 Marriage Match IV(spfa+最大流)
- hdu 3416 Marriage Match IV【SPFA+最大流Dinic】
- HDU 3416 Marriage Match IV【SPFA+最大流】
- hdu 3416 Marriage Match IV 【图论-网络流-最短路+最大流(spfa + Dinic)】
- 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 (SPFA+Dinic)
- Hdu 3416 Marriage Match IV 最大流sap+最短路径spfa
- Marriage Match IV (hdu 3416 网络流+spfa最短路)
- hdu 3416 Marriage Match IV 最大流 最短路径
- hdu 3416 Marriage Match IV 【网络最大流+最短路】
- [HDU 3416]Marriage Match IV[最大流][最短路]
- Android检查是否已经连接到网络
- Opencv vector
- java中的注解
- (lintcode)第7题二叉树的序列化和反序列化
- github中出现的问题
- HDU 3416 Marriage Match IV (SPFA+最大流)
- sql之left join、right join、inner join的区别
- [leetcode]668. Kth Smallest Number in Multiplication Table
- 源码安装tensorflow
- [知了堂学习笔记]_css3特效第二篇--行走的线条&&置顶导航栏
- Android去除字符串中空格制表符换行
- UI组件——WebView部分api释义
- Sasha and Sticks CodeForces
- 电池高压安全注意事项