hdu_6437_Videos_(最大费用最大流)

版权声明: https://blog.csdn.net/yyy_3y/article/details/82016453

传送门

题意:
1)一天有n个小时,m个c菌的视频(一共有2中类型的视频,如果观看不同类型的视频将会扣除一个w(定值)的快乐值),k个人。
2)现在给出m个视频的s(开始时间),t(结束时间),w(看视频所能获得的快乐值),t(类型)。
3)没个视频只能最多由一个人观看。
4)求这群人最大的快乐值。

define:(from,to,cap,cost),源点为s,次源点为ss,汇点为t。
思路:
1) 因为是k个人,我们需要建立一个次源点来保证。(s,ss,k,0)
2)拆点,保证每段视频只有一个人观看
3)在对于每段视频,找到一段开始时间比他本身结束大的,就建边(i+m,j,inf,w),如果是同类型的就是0,不同类型的是-w。
4)因为求的是最大的快乐值,模板是取最小费用。所以添加一个符号就行(也就是为什么是-
w的原因)
这里写图片描述

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define UINT unsigned LL
#define MAXN (100000+100)
#define lnn putchar('\n')
#define see putchar(' ')
using namespace std;
const LL maxn=1e5+7;
const LL MOD=1e9+7;
inline LL read()
{
    LL X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
inline void write(LL x)
{
     if(x<0) putchar('-'),x=-x;
     if(x>9) write(x/10);
     putchar(x%10+'0');
}
const LL M=1000001;
const LL N=5500;
const LL inf=0x3f3f3f3f3f3f3f3f;
LL head[N],n,m,cnt;
struct node{
    LL to,cap,money,next;
}edge[M];
struct MCMF{
    LL len[N];
    LL pre[N];
    LL path[N];
    bool vis[N];
    void init()
    {
        memset(head,-1,sizeof head);
        cnt=0;
    }
    void add(LL u,LL v,LL cap,LL money)
    {
        edge[cnt].to=v;
        edge[cnt].cap=cap;
        edge[cnt].next=head[u];
        edge[cnt].money=money;
        head[u]=cnt++;

        edge[cnt].to=u;
        edge[cnt].cap=0;
        edge[cnt].next=head[v];
        edge[cnt].money=-money;
        head[v]=cnt++;
    }
    bool spfa(LL s,LL t)
    {
        memset(vis,false,sizeof vis);
        memset(pre,-1,sizeof pre);
        memset(path,-1,sizeof path);
        memset(len,inf,sizeof len);
        queue<LL> q;
        q.push(s);
        vis[s]=true;
        len[s]=0;
        while(!q.empty()){
            LL u=q.front();
            q.pop();
            vis[u]=false;
            for(LL i=head[u];i!=-1;i=edge[i].next){
                LL v=edge[i].to;
                if(len[v]>len[u]+edge[i].money && edge[i].cap>0){
                    len[v]=len[u]+edge[i].money;
                    pre[v]=u;
                    path[v]=i;
                    if(!vis[v]){
                        vis[v]=true;
                        q.push(v);
                    }
                }
            }
        }
        return len[t]!=inf;
    }
    LL MinCostMaxFlow(LL s,LL t)
    {
        LL sum=0;
        while(spfa(s,t)){
            LL mmin=inf;
            for(LL i=t;i!=s && i!=-1;i=pre[i]){
                mmin=min(mmin,edge[path[i]].cap);

            }
           for(LL i=t;i!=s && i!=-1;i=pre[i]){
                edge[path[i]].cap-=mmin;
                edge[path[i]^1].cap+=mmin;
            }
            sum+=mmin*(len[t]);
        }
        return sum;
    }
};
LL xx[N],yy[N],zz[N],ww[N];
int main()
{
    MCMF mcmf;
    LL T;
    for(scanf("%lld",&T);T--;){
        mcmf.init();
        LL n,m,k,w; scanf("%lld%lld%lld%lld",&n,&m,&k,&w);
        LL S=2*m+1,T=2*m+3,SS=2*m+2;
        mcmf.add(S,SS,k,0);
        for(LL i=1;i<=m;i++)   scanf("%lld%lld%lld%lld",&xx[i],&yy[i],&zz[i],&ww[i]);

        for(LL i=1;i<=m;i++){
            mcmf.add(i,i+m,1,-zz[i]);
            mcmf.add(SS,i,inf,0);
            mcmf.add(i+m,T,inf,0);
            for(LL j=1;j<=m;j++){
                if(i==j) continue;
                if(yy[i]<=xx[j]){
                    if(ww[i]==ww[j]) mcmf.add(i+m,j,1,w);
                    else mcmf.add(i+m,j,1,0);
                }
            }
        }
        printf("%lld\n",-mcmf.MinCostMaxFlow(S,T));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yyy_3y/article/details/82016453