zoukankan      html  css  js  c++  java
  • 【最短路+最大流】上学路线@安徽OI2006

    【最短路+最大流】上学路线@安徽OI2006

    PROBLEM

    洛谷P4300

    SOLUTION

    先在原图上跑单源最短路,找出包含所有最短路径的子图。
    要使从S到T的最短路变长,那么在子图中S到T不再连通,要求代价最小,即在子图上找最小割。
    因为“最小割等于最大流“,所以在子图上跑一遍最大流。
    自己犯蠢,最短路子图建的双向边,wa了好几发

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 505;
    const int MAXE = 124755*2;
    const ll INF = 1247550005;
    int n,m;
     
    struct data {
        int u,v,t,c;
    } da[MAXE*2];
     
    struct Graph1 {
        struct edge {
            int v,t,nex;
        } ed[MAXE];
        int head[MAXN],tot;
        void addedge(int u,int v,int t) {
            tot++;
            ed[tot].v = v;
            ed[tot].t = t;
            ed[tot].nex = head[u];
            head[u] = tot;
        }
        ll d[MAXN];int p[MAXN];
        bool vis[MAXN];
        priority_queue<pair<ll,int> >q;
        void dijkstra(int st) {
            fill(d,d+n+1,INF);
            memset(vis,0,sizeof vis);
            d[st] = 0;
            q.push({0,st});
            while(q.size()) {
                int x = q.top().second;
                q.pop();
                if(vis[x])
                    continue;
                vis[x] = 1;
                for(int i = head[x]; i; i=ed[i].nex) {
                    int y = ed[i].v,z = ed[i].t;
                    if(d[y]>d[x]+z) {
                        d[y] = d[x] + z;
                        q.push({-d[y],y});
                        p[y] = i;
                    }
                }
            }
        }
        bool flag[MAXE];
        queue<int> q2;
        void bfs() {
            memset(flag,0,sizeof flag);
            memset(vis,0,sizeof vis);
            q2.push(n);
            while(q2.size()) {
                int x = q2.front();
                q2.pop();
                if(vis[x])
                    continue;
                vis[x] = 1;
                int pre = p[x];
                for(int i = head[x]; i; i=ed[i].nex) {
                    int y = ed[i].v,z = ed[i].t;
                    if((i^1) == pre||d[y] + z == d[ed[pre^1].v] + ed[pre^1].t) {
                        flag[i^1] = 1;
                        q2.push(y);
                    }
                }
            }
        }
    } G1;
     
    struct Graph2 {
        int head[MAXN],ver[MAXE<<1],Next[MAXE<<1],d[MAXN];
        int s,t,tot;
        ll maxflow,edge[MAXE<<1];
        queue<int> q;
        void add(int x,int y,int z) {
            ver[++tot] = y,edge[tot] = z,Next[tot] = head[x],head[x] = tot;
            ver[++tot] = x,edge[tot] = 0,Next[tot] = head[y],head[y] = tot;
        }
        bool bfs() {
            memset(d,0,sizeof d);
            while(q.size())
                q.pop();
            q.push(s);
            d[s] = 1;
            while(q.size()) {
                int x = q.front();
                q.pop();
                for(int i = head[x]; i; i=Next[i])
                    if(edge[i]&&!d[ver[i]]) {
                        q.push(ver[i]);
                        d[ver[i]] = d[x] + 1;
                        if(ver[i]==t)
                            return 1;
                    }
            }
            return 0;
        }
        ll dinic(int x,ll flow) {
            if(x==t)
                return flow;
            ll rest = flow,k;
            for(int i = head[x]; i && rest; i=Next[i])
                if(edge[i]&&d[ver[i]] == d[x] + 1) {
                    k = dinic(ver[i],min(rest,(ll)edge[i]));
                    if(!k)
                        d[ver[i]] = 0;
                    edge[i] -= k;
                    edge[i^1] += k;
                    rest-=k;
                }
            return flow - rest;
        }
    } G2;
     
    int main() {
        scanf("%d%d",&n,&m);
        G1.tot = 1;
        for(int i=1; i<=m; i++) {
            int u,v,t,c;
            scanf("%d%d%d%d",&u,&v,&t,&c);
            da[i*2] = {u,v,t,c};
            da[i*2+1] = {v,u,t,c};
            G1.addedge(u,v,t);
            G1.addedge(v,u,t);
        }
        G1.dijkstra(1);
        G1.bfs();
        G2.s = 1;
        G2.t = n;
        G2.tot = 1;
        for(int i=2; i<=G1.tot; i++) {
            if(G1.flag[i]) {
                int x = da[i].u,y = da[i].v,c = da[i].c;
                G2.add(x,y,c);
            }
        }
        ll flow = 0;
        while(G2.bfs())
            while(flow=G2.dinic(G2.s,INF))
                G2.maxflow += flow;
        cout<<G1.d[n]<<endl;
        cout<<G2.maxflow<<endl;
        return 0;
    }
    
  • 相关阅读:
    JS 缓动动画封装函数
    JS 实现商品图片放大镜(大图)效果
    JS 实现春节倒计时效果
    HMTL+CSS 实现图片旋转木马效果
    HTML 解决video标签播放视频看不见&能听到声音看不到画面等问题
    GoLang Json数据的的序列化与反序列化
    GoLang 解决VsCode中提示错误 go: cannot find main module, but found .git/config in D:XXXsrcXXX to create a module there, run: cd .. && go mod init
    Flutter 容器(3)
    Flutter 容器 (2)
    Flutter 容器 (1)
  • 原文地址:https://www.cnblogs.com/NeilThang/p/9982041.html
Copyright © 2011-2022 走看看