hdu 6437 Problem L.Videos (最小费用最大流)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/imzxww/article/details/82054498

http://acm.hdu.edu.cn/showproblem.php?pid=6437

题意:

一天有N个小时,有m个节目(每种节目都有类型),有k个人,连续看相同类型的节目会扣w快乐值

每一种节目有都一个播放区间[s,t]。每个人同一时间只能看一个节目,看完可以获得快乐值。问最多可以获得多少快乐?

思路:

我们可以将每部电影拆成两个点来看,建立源点和汇点,还有次源点,因为要求的是最大费用,这样我们可以把费用变成负数,这样就是求最小费用,最后变成正数就是最大费用了。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int inf=0x7fffffff;
struct edge
{
    int from,to,cap,flow,cost;
    edge(int u,int v,int c,int f,int co):
        from(u),to(v),cap(c),flow(f),cost(co) {};
};
struct node
{
    int s,t,w,op;
}a[maxn];
int n,s,t,m,K,W;
vector<int>g[maxn];
vector<edge>e;
void addedge(int u,int v,int c,int cost)
{
    e.push_back(edge(u,v,c,0,cost));
    e.push_back(edge(v,u,0,0,-cost));
    int zz=e.size();
    g[u].push_back(zz-2);
    g[v].push_back(zz-1);
}
int cost;
void init(int N)
{
    cost=0;
    for(int i=0; i<=N; i++)
    {
        g[i].clear();
    }
    e.clear();
}
int dis[maxn],pre[maxn],vis[maxn];
bool spfa()
{
    queue<int>q;
    for(int i=0; i<=t; i++)dis[i]=inf,pre[i]=0;
    dis[s]=0;
    memset(vis,0,sizeof(vis));
    vis[s]=1;
    q.push(s);
    int a=inf;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=0; i<g[u].size(); i++)
        {
            edge f=e[g[u][i]];
            if(f.cap>f.flow&&dis[f.to]>dis[u]+f.cost)
            {
                dis[f.to]=dis[u]+f.cost;
                pre[f.to]=g[u][i];
                a=min(a,f.cap-f.flow);
                if(!vis[f.to])
                {
                    vis[f.to]=1;
                    q.push(f.to);
                }
            }
        }
    }
    if(dis[t]==inf)return 0;
    int u=t;
    cost+=dis[t]*a;
    while(u!=s)
    {
        e[pre[u]].flow+=a;
        e[pre[u]^1].flow-=a;
        u=e[pre[u]].from;
    }
    return 1;
}
void mincost()
{
    while(spfa())
    {
        continue;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&n,&m,&K,&W);
        init(2*m+2);
        addedge(0,2*m+1,K,0);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&a[i].s,&a[i].t,&a[i].w,&a[i].op);
            addedge(i,i+m,1,-a[i].w);
            addedge(i+m,2*m+2,1,0);
            addedge(2*m+1,i,1,0);
        }
        s=0,t=2*m+2;
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(i==j)continue;
                if(a[i].t<=a[j].s)
                {
                    addedge(i+m,j,1,(a[i].op == a[j].op ? W : 0));
                }
            }
        }
        mincost();
        printf("%d\n",-cost);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/82054498