您的位置:首页 > 其它

HDU 3416 Marriage Match IV【最短路 + 最大流】经典模型好题

2018-02-13 17:04 405 查看
传送门

题意: 给定一幅单向图(n, m), 起点和终点, 问起点到终点有所少条最短路径, 每条边只能做一遍.

思路: 如果没有只走一遍的限制, 那么就是个很简单的最短路了. 关键在于只能走一遍. 那么我们就想跑最短路吧图中有用的边先存下来, 重新建图, 让每条边的流量的为1, 然后跑s - t 的最大流就是ans. 有用的边为(假设dis1表示从s出发的最短路, dis2表示t出发的最短路.) 那么就是dis1[u] + w + dis2[v] = dis1[t], 然后就是上板子即可, 主要是这个模型很重要, 边只能经过一次那么我们就设流量为1, 那就是最大流. 这种模型才是本道题的精华所在.

AC Code

const int maxn = 1e3 + 5;
const int maxm = 1e5+5;
int head1[maxn], cnt1;
int n, m, s, t;
bool vis1[maxn];
int d[maxn], cur[maxn];
struct node1 {
int u, v;
int cap, flow, next;
} e[maxm*2]; //因为是双向边  所以记得开二倍

void init1() {
cnt1 = 0;
Fill(head1, -1);
}

void add1(int u, int v, int c, int f) {
e[cnt1] = node1{u, v, c, f, head1[u]};
head1[u] = cnt1++;
}

bool BFS() {
queue<int> q; q.push(s);
Fill(vis1,0); vis1[s] = 1;
d[s] = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head1[u] ; ~i ; i = e[i].next) {
int to = e[i].v;
if (!vis1[to] && e[i].cap > e[i].flow) { //只考虑残量网络的弧
vis1[to] = 1;
d[to] = d[u] + 1;
q.push(to);
}
}
}
return vis1[t];
}

int dfs(int x, int a) {
if (x == t || a == 0) return a;
int flow = 0, f;
int &i = cur[x];
for (i = head1[x] ; ~i ; i = e[i].next) { //从上次考虑的弧
int to = e[i].v;
if (d[to]== d[x] + 1 && (f = dfs(to, min(a, e[i].cap - e[i].flow))) > 0) {
e[i].flow += f;
e[i^1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}

int Dinic() {
int maxflow = 0;
while (BFS()) {
Fill(cur, 0);
maxflow += dfs(s, inf);
}
return maxflow;
}

struct node2 {
int to, next, w;
bool operator < (const node2 & a) const {
return w > a.w;
}
} g[maxm];
int cnt2 , head2[maxn];
void init2() {
cnt2 = 0;
Fill(head2, -1);
}
void add2(int u, int v, int w) {
g[cnt2] = node2{v, head2[u], w};
head2[u] = cnt2++;
}
int dis[2][maxn];
int vis2[maxn];
void dij(int st, int id)
{
priority_queue<node2> q;
Fill(dis[id],inf); Fill(vis2,0);
dis[id][st] = 0;
q.push((node2){st, 0, 0});
while (!q.empty()) {
node2 u = q.top();
q.pop();
if(vis2[u.to]) continue;
vis2[u.to] = 1;
for (int i = head2[u.to]; ~i ; i = g[i].next) {
int to = g[i].to;
if (dis[id][to] > dis[id][u.to] + g[i].w) {
dis[id][to] = dis[id][u.to] + g[i].w;
q.push((node2){to, 0, dis[id][to]});
}
}
}
}
bool is[maxm];
struct gg {
int u, v, w;
} pp[maxm];
void solve() {
scanf("%d%d", &n, &m);
init2(); Fill(is, false);
for (int i = 1 ; i <= m ; i ++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add2(u, v, w);
pp[i].u = u; pp[i].v = v; pp[i].w = w;
}
scanf("%d%d", &s, &t);
dij(s, 0);
init2();
for (int i = 1 ; i <= m ; i ++) {
add2(pp[i].v, pp[i].u, pp[i].w);
}
dij(t, 1);
for (int i = 1 ; i <= m ; i ++) {
int tmp = dis[0][pp[i].u];
tmp += pp[i].w + dis[1][pp[i].v];
if (tmp == dis[0][t]) is[i] = true;
}
init1();
for (int i = 1 ; i <= m ; i ++) {
if (!is[i]) continue;
add1(pp[i].u, pp[i].v, 1, 0);
add1(pp[i].v, pp[i].u, 0, 0);
}
printf("%d\n", Dinic());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: