zoukankan      html  css  js  c++  java
  • HDU3416 Marriage Match IV(最短路+网络流)

    给出一个有向图和起点、终点,每条路径只能走一次,询问从起点到终点能重复的走几次。

    做法就是从起点到终点来回跑两遍最短路,建一个最短路网络流图。

    无需考虑重边和自环,这些不影响Dinic算法的执行。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+100;
    const int inf=1e9+100;
    int n,m;
    struct node {
        int u,v,w,nxt;
    }edge[maxn<<1];
    int head[maxn],tot;
    void addedge (int u,int v,int w) {
        edge[tot].u=u;
        edge[tot].v=v;
        edge[tot].w=w;
        edge[tot].nxt=head[u];
        head[u]=tot++;
    } 
    int dep[maxn],inq[maxn],cur[maxn],wjm,maxflow,s,t;
    bool bfs () {
        for (int i=0;i<=t;i++) {
            cur[i]=head[i];
            dep[i]=inf;
            inq[i]=0;
        }
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (q.size()) {
            int u=q.front();
            q.pop();
            inq[u]=0;
            for (int i=head[u];i!=-1;i=edge[i].nxt) {
                int v=edge[i].v;
                if (dep[v]>dep[u]+1&&edge[i].w) {
                    dep[v]=dep[u]+1;
                    if (inq[v]==0) {
                        q.push(v);
                        inq[v]=1;
                    }
                }
            }
        }
        if (dep[t]!=inf) return 1;
        return 0;
    }
    int dfs (int u,int flow) {
        int increase=0;
        if (u==t) {
            wjm=1;
            maxflow+=flow;
            return flow;
        }
        int used=0;
        for (int i=cur[u];i!=-1;i=edge[i].nxt) {
            cur[u]=i;
            int v=edge[i].v;
            if (edge[i].w&&dep[v]==dep[u]+1) {
                if (increase=dfs(v,min(flow-used,edge[i].w))) {
                    used+=increase;
                    edge[i].w-=increase;
                    edge[i^1].w+=increase;
                    if (used==flow) break;
                }
            }
        }
        return used;
    }
    int Dinic () {
        while (bfs()) {
            wjm=1;
            while (wjm==1) {
                wjm=0;
                dfs(s,inf);
            }
        }
        return maxflow;
    }
    
    long long d[maxn][2];
    int vis[maxn];
    struct qnode {
        int v;
        int w;
        qnode (int vv,int ww) {
            v=vv;
            w=ww;
        }
        bool operator < (const qnode &r) const {
            return w>r.w;
        } 
    };
    void dij (int s,int f) {
        for (int i=1;i<=n;i++) d[i][f]=inf,vis[i]=0;
        priority_queue<qnode> q;
        d[s][f]=0;
        q.push(qnode(s,d[s][f]));
        while (q.size()) {
            qnode tt=q.top();
            q.pop();
            int u=tt.v;
            vis[u]=1;
            for (int i=head[u];i!=-1;i=edge[i].nxt) {
                int v=edge[i].v;
                if (vis[v]) continue;
                if (d[u][f]+edge[i].w<d[v][f]) {
                    d[v][f]=d[u][f]+edge[i].w;
                    q.push(qnode(v,d[v][f]));
                }
            }
        }
    }
    struct E {
        int u,v,w;
        bool operator < (const E &r) const {
            return w<r.w;
        }
    }e[maxn];
    int F[maxn]; 
    int main () {
        int _;
        scanf("%d",&_);
        while (_--) {
            scanf("%d%d",&n,&m);
            for (int i=1;i<=n;i++) head[i]=-1,tot=0;
            for (int i=1;i<=m;i++) F[i]=0;
            for (int i=1;i<=m;i++) {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                e[i]={u,v,w};
            }
            sort(e+1,e+m+1);
            for (int i=1;i<=m;i++) {
                if (e[i].u==e[i].v) continue;
                addedge(e[i].u,e[i].v,e[i].w);
            }
            int A,B;
            scanf("%d%d",&A,&B);
            dij(A,0);
            for (int i=0;i<=n+1;i++) head[i]=-1;tot=0;
            for (int i=1;i<=m;i++) {
                if (e[i].u==e[i].v) continue;
                addedge(e[i].v,e[i].u,e[i].w);
            }
            dij(B,1);
            s=0;t=n+1;
            for (int i=0;i<=n+1;i++) head[i]=-1;tot=0;wjm=0;maxflow=0;
            addedge(s,A,inf);addedge(A,s,0);
            for (int i=1;i<=m;i++) {
                int u=e[i].u,v=e[i].v,w=e[i].w;
                if (u==v) continue;
                if (d[u][0]+w+d[v][1]==d[B][0]) {
                    addedge(u,v,1);
                    addedge(v,u,0);
                }
            }
            addedge(B,t,inf);addedge(t,B,0);
            printf("%d
    ",Dinic());
        }
    }
  • 相关阅读:
    运维:生产日志重复打印了,赶紧来看看~
    就这样,我走过了程序员的前五年。一路风雨泥泞,前方阳光正好。
    一个排序引发的BUG
    曝光一个网站,我周末就耗在上面了。
    我不服!这开源项目居然才888个星!?
    知乎的一次29.7元的咨询
    面试官:啥是请求重放呀?
    414天前,我以为这是编程玄学...
    老爷子这代码,看跪了!
    面试官一个线程池问题把我问懵逼了。
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14048804.html
Copyright © 2011-2022 走看看