zoukankan      html  css  js  c++  java
  • hdu 6437 /// 最小费用最大流 负花费 SPFA模板

    题目大意:

    给定n,m,K,W 

    表示n个小时 m场电影(分为类型A、B)

    K个人 若某个人连续看了两场相同类型的电影则失去W 电影时间不能重叠

    接下来给定m场电影的 s t w op 

    表示电影的 开始时间s 结束时间t 看完这场电影则获得w 电影类型是op(0为A 1为B)

    将一场电影拆成两个点 s t,两点间连线花费为-w容量为1

    源点与所有电影的s点连线 花费为0容量为1

    所有电影的t点与汇点连线 花费为0容量为1

    若两场电影的时间不冲突 那么按时间顺序在之间连边

    若类型相同 花费为W容量为1 否则 花费为0容量为1

    最后设超级源点与源点连边 花费为0容量为K 表示最多K个人

    此时求出的 最小花费最大流 的最小花费 就是 最后最少的失去

    最少的失去 就是 最大的获得的相反数

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define INF 0x3f3f3f3f
    #define mem(i,j) memset(i,j,sizeof(i))
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int N=405;
    const int mod=1e9+7;
    
    int n,m;
    struct NODE { int s,t,w,op; }node[205];
    struct Edge
    {
        int from,to,cap,flow,cost;
        Edge(int u,int v,int ca,int f,int co):from(u),to(v),cap(ca),flow(f),cost(co){};
    };
    
    struct MCMF
    {
        int n,m,s,t;
        vector<Edge> edges;
        vector<int> G[N];
        int inq[N];//是否在队列中
        int d[N];//距离
        int p[N];//上一条弧
        int v[N];//可改进量
    
        void init(int n) //初始化 顶点为 0~n-1
        {
            this->n=n;
            for(int i=0;i<=n;i++) G[i].clear();
            edges.clear();
        }
    
        void AddEdge(int from,int to,int cap,int cost)//加边
        {
            edges.push_back(Edge(from,to,cap,0,cost));
            edges.push_back(Edge(to,from,0,0,-cost));
            int m=edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
    
        bool SPFA(int s,int t,int &flow,int &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost
        {
            for(int i=0;i<n;i++) d[i]=INF;
            memset(inq,0,sizeof(inq));
            d[s]=0;inq[s]=1;p[s]=0;v[s]=INF;
            queue<int>Q; Q.push(s);
            while(!Q.empty()) {
                int u=Q.front(); Q.pop();
                inq[u]--;  
                for(int i=0;i<G[u].size();i++) {
                    Edge& e=edges[G[u][i]];
                    if(e.cap>e.flow && d[e.to]>d[u]+e.cost) {//满足可增广且可变短
                        d[e.to]=d[u]+e.cost;
                        p[e.to]=G[u][i];
                        v[e.to]=min(v[u],e.cap-e.flow);
                        if(!inq[e.to]) inq[e.to]++,Q.push(e.to);
                    }
                }
            } 
            if(d[t]==INF) return false;//汇点不可达则退出
            flow+=v[t];
            cost+=d[t]*v[t];
            int u=t;
            while(u!=s) {//更新正向边和反向边 
                edges[p[u]].flow+=v[t];
                edges[p[u]^1].flow-=v[t];
                u=edges[p[u]].from;
            }
            return true;
        }
    
        int MincotMaxflow(int s,int t)
        {
            int flow=0,cost=0;
            while(SPFA(s,t,flow,cost));
            return cost;
        }
    }MM;
    
    int main()
    {
        int _; scanf("%d",&_);
        while(_--) {
            int n,m,K,W;
            scanf("%d%d%d%d",&n,&m,&K,&W);
            MM.init(2*m+3);
            inc(i,1,m) {
                int s,t,w,op;
                scanf("%d%d%d%d",&s,&t,&w,&op);
                node[i]={s,t,w,op};
                MM.AddEdge(i*2,i*2+1,1,-w);
                MM.AddEdge(1,i*2,1,0);
                MM.AddEdge(i*2+1,m*2+2,1,0);
            }
            inc(i,1,m) inc(j,i+1,m) {
                if(node[i].t<=node[j].s) {
                    if(node[i].op==node[j].op)
                        MM.AddEdge(i*2+1,j*2,1,W);
                    else MM.AddEdge(i*2+1,j*2,1,0);
                }
                if(node[j].t<=node[i].s) {
                    if(node[i].op==node[j].op)
                        MM.AddEdge(j*2+1,i*2,1,W);
                    else MM.AddEdge(j*2+1,i*2,1,0);
                }
            }
            MM.AddEdge(0,1,K,0);
            int ans=MM.MincotMaxflow(0,m*2+2);
            printf("%d
    ",-ans);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    0601 新的冲刺
    0527 演示内容
    0525 项目回顾7.0
    0523 Scrum项目6.0
    0518 Scrum项目5.0
    Scrum 4.0
    0512 操作系统进程调度实验
    0511 backlog 项目管理
    复利计算器之单元测试
    操作系统的实验一实验报告
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10447816.html
Copyright © 2011-2022 走看看