HDU - 3416 Marriage Match IV(最短路+最大流)

http://acm.hdu.edu.cn/showproblem.php?pid=3416

题意:

A要去B,有很多路,A要走最短路,每次走过就不能再走了,问有几种走法

思路:

首先题目上给了很多路,但有些路是不需要的,因为走最短路的时候不会走到它,所以要被这些路给剔除掉。怎么剔除呢,可以先跑一下最短路,把最短路可以走的边建到最大流的边里,权值为1,那么这样不走的边就不会建到里面。
那么怎么用最短路把能走边给标记出来呢,因为最短路中两个相连的点之间的距离恰好是距源点S的距离之差,这样只需要跑一边啊最短路就可以把边给建好^-^
这里写图片描述
如图所示,因为dis[3]-dis[1]!=3所以1->3这条边不是最短路的边

但是存边的时候不能用矩阵存,会WA,原因我还没找到,很难受的说。

#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <stdio.h>
#include <deque>

using namespace std;

#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define maxn 1000005
#define eps 0.00000001
#define PI acos(-1.0)
#define M 1000000007

struct Edge {
    int v, w, nxt;
}edge[maxn];

struct Link{
    int v, dis;
    Link(){}
    Link(int _v, int _dis) {
        v = _v; dis = _dis;
    }
};
vector<Link> vec[1005];
int head[maxn], tot, S, T, dis[maxn], cur[maxn], vis[maxn], aug[maxn],pre[maxn], gap[maxn];
int n, m;

void addEdge(int u, int v, int w)  {
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].nxt = head[u];
    head[u] = tot ++;

    edge[tot].v = u;
    edge[tot].w = 0;
    edge[tot].nxt = head[v];
    head[v] = tot ++;
}

void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
}
//Dijkstra
void Dijkstra() {
    memset(vis, 0, sizeof(vis));
    memset(dis, INF, sizeof(dis));
    dis[S] = 0;
    for (int i = 1; i <= n; i ++) {
        int u = -1, MinDis = INF;
        for (int j = 1; j <= n; j ++)
            if(!vis[j] && MinDis > dis[j]) {
                MinDis = dis[j];
                u = j;
            }
        if(u == -1) break;
        vis[u] = 1;
        for (int j = 0; j < (int)vec[u].size(); j ++) {
            Link t = vec[u][j];
            if(!vis[t.v] && dis[t.v] > dis[u] + t.dis)
                dis[t.v] = dis[u] + t.dis;
        }
    }
}

/* //SPFA
void SPFA() {
    queue<int> q;
    memset(dis, INF, sizeof(dis));
    dis[S] = 0;//起始点
    memset(vis, 0, sizeof(vis));//全赋初值
    q.push(S);
    vis[S] = 1;//如队列就标记
    while(!q.empty()) {
        int x = q.front(); q.pop();//队列头拿出
        vis[x] = 0;//取消标记
        for (int j = 0; j < vec[x].size(); j ++) {//松弛相关点
            Link t = vec[x][j];
            if (dis[t.v] > dis[x] + t.dis) {
                dis[t.v] = dis[x] + t.dis;
                if (!vis[t.v]) {//如果此时这个点不在队列中,如队
                    vis[t.v] = 1;//并标记
                    q.push(t.v);//如对
                }
            }
        }
    }
}
 */
/*
 //dinic
int bfs() {
    memset(dis, -1, sizeof(dis));
    dis[T] = 0;
    queue<int> que;
    que.push(T);
    while(!que.empty()) {
        int u = que.front(); que.pop();
        for (int i = head[u]; i + 1; i = edge[i].nxt) {
            if(dis[edge[i].v] == -1 && edge[i ^ 1].w > 0) {
                dis[edge[i].v] = dis[u] + 1;
                que.push(edge[i].v);
            }
        }
    }
    return dis[S] != -1;
}

int dfs(int u, int flow) {
    if(u == T) return flow;
    int belta = flow;
    for (int &i = cur[u]; i + 1; i = edge[i].nxt) {
        if(dis[u] == dis[edge[i].v] + 1 && edge[i].w > 0) {
            int d = dfs(edge[i].v, min(belta, edge[i].w));
            edge[i].w -= d; edge[i ^ 1].w += d;
            belta -= d;
            if(belta == 0) break;
        }
    }
    return flow - belta;
}

int dinic() {
    int ans = 0;
    while(bfs()) {
        for (int i = 1; i <= n; i ++)
            cur[i] = head[i];
        ans += dfs(S, INF);
    }
    return ans;
}
*/
//SAP
int SAP(int n){
    int max_flow = 0,u = S, v;
    int id, mindep;
    aug[S] = INF;
    pre[S] = -1;
    memset(dis, 0, sizeof(dis));
    memset(gap, 0, sizeof(gap));
    gap[0] = n;
    for(int i = 0; i <= n; i ++)
        cur[i] = head[i];
    while(dis[S] < n){
        int flag = 0;
        if(u == T){
            max_flow += aug[T];
            for(v= pre[T]; v + 1; v = pre[v]){
                id = cur[v];
                edge[id].w -= aug[T];
                edge[id^1].w += aug[T];
                aug[v] -= aug[T];
                if(edge[id].w == 0)
                    u = v;
            }
        }
        for(int i = cur[u]; i != -1; i = edge[i].nxt){
            v = edge[i].v;
            if(edge[i].w > 0 && dis[u] == dis[v] + 1){
                flag = 1;
                pre[v] = u;
                cur[u] = i;
                aug[v] = min(aug[u], edge[i].w);
                u = v;
                break;
            }
        }
        if(!flag){
            if(--gap[dis[u]] == 0)
                break;
            mindep = n;
            cur[u] = head[u];
            for(int i = head[u]; i != -1; i = edge[i].nxt){
                v = edge[i].v;
                if(edge[i].w > 0 && dis[v] < mindep){
                    mindep = dis[v];
                    cur[u] = i;
                }
            }
            dis[u] = mindep + 1;
            gap[dis[u]] ++;
            if(u != S)
                u = pre[u];
        }
    }
    return max_flow;
}

int main(int argc, const char * argv[]) {
    int TT;
    scanf("%d", &TT);
    while(TT --) {
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; i ++)
            vec[i].clear();
        for (int i = 0; i < m; i ++) {
            int u, v, w;
            scanf("%d %d %d", &u, &v, &w);
            vec[u].push_back(Link(v, w));
        }
        scanf("%d %d", &S, &T);
        Dijkstra();
        if(dis[T] == 0){
            printf("0\n");
            continue;
        }
        init();
        for (int i = 1; i <= n; i ++) {
            for (int j = 0; j < (int)vec[i].size(); j ++) {
                Link t = vec[i][j];
                if(dis[i] + t.dis == dis[t.v])
                    addEdge(i, t.v, 1);
            }
        }
        printf("%d\n", SAP(n + 1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/81974243
今日推荐