zoukankan      html  css  js  c++  java
  • luogu P4542 [ZJOI2011]营救皮卡丘 网络流 拆点

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<iostream>
    using namespace std;
    const int maxn=1e6+10;
    const int inf=0x3f3f3f3f;
    bool vis[maxn];
    int n,m,K,s,t,x,y,z,f,cost[maxn],pre[maxn],last[maxn],flow[maxn],maxflow,mincost;
    //cost最小花费;pre每个点的前驱;last每个点的所连的前一条边;flow源点到此处的流量
    //maxflow 最大流量
    //mincost 最大流量的情况下的最小花费
    struct Edge
    {
        int to,next,flow,cost;//flow流量 cost花费
    } edge[maxn];
    int d[210][210];
    int head[maxn],num_edge;
    queue <int> q;
    void add(int from,int to,int flow,int cost)
    {
        edge[++num_edge].next=head[from];
        edge[num_edge].to=to;
        edge[num_edge].flow=flow;
        edge[num_edge].cost=cost;
        head[from]=num_edge;
    
        edge[++num_edge].next=head[to];
        edge[num_edge].to=from;
        edge[num_edge].flow=0;
        edge[num_edge].cost=-cost;
        head[to]=num_edge;
    }
    bool spfa(int s,int t)
    {
        memset(cost,0x7f,sizeof(cost));
        memset(flow,0x7f,sizeof(flow));
        memset(vis,0,sizeof(vis));
        q.push(s);
        vis[s]=1;
        cost[s]=0;
        pre[t]=-1;
        while (!q.empty())
        {
            int now=q.front();
            q.pop();
            vis[now]=0;
            for (int i=head[now]; i!=-1; i=edge[i].next)
            {
                if (edge[i].flow>0 && cost[edge[i].to]>cost[now]+edge[i].cost)//正边
                {
                    cost[edge[i].to]=cost[now]+edge[i].cost;
                    pre[edge[i].to]=now;
                    last[edge[i].to]=i;
                    flow[edge[i].to]=min(flow[now],edge[i].flow);//
                    if (!vis[edge[i].to])
                    {
                        vis[edge[i].to]=1;
                        q.push(edge[i].to);
                    }
                }
            }
        }
        return pre[t]!=-1;
    }
    
    void MCMF()
    {
        while (spfa(s,t))
        {
            int now=t;
            maxflow+=flow[t];
            mincost+=flow[t]*cost[t];
            while (now!=s)
            {
                //从源点一直回溯到汇点
                edge[last[now]].flow-=flow[t];//flow和cost容易搞混
                edge[last[now]^1].flow+=flow[t];
                now=pre[now];
            }
        }
    }
    signed main()
    {
        memset(head,-1,sizeof(head));
        num_edge=-1;
        cin>>n>>m>>K;
        s=n*2+2,t=s+1;
        for(int i=0; i<=n; i++)
            for(int j=0; j<=n; j++)
                if(i!=j)
                    d[i][j]=inf;
        for(int i=1; i<=m; i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            d[x][y]=d[y][x]=min(d[x][y],z);
        }
        for(int k = 0; k <= n; ++k)
            for(int i = 0; i <= n; ++i)
                for(int j = 0; j <= n; ++j)
                    if(k < max(i, j) && d[i][j] > d[i][k] + d[k][j])
                        d[i][j] = d[i][k] + d[k][j];
        //拆点
        //源点向0的入点连流量k费用0的边,表示最多经过0 K次
        //源点向其余每个点的入点连流量1费用0的边
        for(int i = 0; i <= n; ++i)
        {
            add(s, i, !i ? K : 1, 0);
            add(i + n + 1, t, 1, 0);//每个点都要被到达一次,0号不用被破坏
            for(int j = i + 1; j <= n; ++j)
                //每个i的入点向j(j>i)连流量1费用d[i][j]的边
                add(i, j + n + 1, 1, d[i][j]);
        }
        MCMF();
        cout<<mincost<<endl;
        return 0;
    }
  • 相关阅读:
    AES算法,DES算法,RSA算法JAVA实现
    spring官方学习地址
    逐步理解SpringMVC
    sublime前端开发工具常用技巧
    谈谈关键字new
    关于mybatisgenerator的问题
    AOPjdk动态代理的思考
    关于java解析xml文件出现的问题
    Java注解
    git向码云上传代码总结
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/13186610.html
Copyright © 2011-2022 走看看