zoukankan      html  css  js  c++  java
  • P2153 [SDOI2009]晨跑

    思路

    典型的最小费用最大流问题,拆点,每个点对应的入点和出点之间连一条cap=1的边表示只能经过一次的限制条件
    然后其他边从u的出点连向v的入点即可

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <queue>
    using namespace std;
    const int MAXN = 1000;
    const int INF = 0x3f3f3f3f;
    struct Edge{
        int u,v,cap,cost,flow;
    };
    int n,m;
    vector<Edge> edges;
    vector<int> G[MAXN];
    void addedge(int u,int v,int cap,int cost){
        edges.push_back((Edge){u,v,cap,cost,0});
        edges.push_back((Edge){v,u,0,-cost,0});
        int cnt=edges.size();
        G[u].push_back(cnt-2);
        G[v].push_back(cnt-1);
    }
    int a[MAXN],d[MAXN],p[MAXN],vis[MAXN],s,t;
    queue<int> q;
    bool spfa(int &flow,int &cost){
        memset(d,0x3f,sizeof(d));
        memset(p,0,sizeof(p));
        memset(vis,0,sizeof(vis));
        q.push(s);
        d[s]=0;
        p[s]=0;
        a[s]=INF;
        vis[s]=true;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            vis[x]=false;
            for(int i=0;i<G[x].size();i++){
                Edge &e = edges[G[x][i]];
                if(e.cap>e.flow&&d[x]+e.cost<d[e.v]){
                    d[e.v]=d[x]+e.cost;
                    a[e.v]=min(a[x],e.cap-e.flow);
                    p[e.v]=G[x][i];
                    if(!vis[e.v]){
                        vis[e.v]=true;
                        q.push(e.v);
                    }
                }
            }
        }
        if(d[t]==INF)
            return false;
        flow+=a[t];
        cost+=a[t]*d[t];
        for(int i=t;i!=s;i=edges[p[i]].u){
            edges[p[i]].flow+=a[t];
            edges[p[i]^1].flow-=a[t];
        }
        return true;
    }
    void MCMF(int &flow,int &cost){
        flow=cost=0;
        while(spfa(flow,cost));
    }
    int main(){
        scanf("%d %d",&n,&m);
        s=1,t=n;
        addedge(1,n+1,INF,0);
        for(int i=2;i<n;i++)
            addedge(i,n+i,1,0);
        addedge(n,2*n,INF,0);
        for(int i=1;i<=m;i++){
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            addedge(n+a,b,1,c);
        }
        int flow,cost;
        MCMF(flow,cost);
        printf("%d %d
    ",flow,cost);
        return 0;
    }
    
  • 相关阅读:
    Educational Codeforces Round 86 (Rated for Div. 2) D. Multiple Testcases
    Educational Codeforces Round 86 (Rated for Div. 2) C. Yet Another Counting Problem
    HDU
    HDU
    HDU
    HDU
    Good Bye 2019 C. Make Good (异或的使用)
    Educational Codeforces Round 78 (Rated for Div. 2) C. Berry Jam
    codeforces 909C. Python Indentation
    codeforces1054 C. Candies Distribution
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10483549.html
Copyright © 2011-2022 走看看