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

Problem L.Videos

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 471    Accepted Submission(s): 227


 

Problem Description

C-bacteria takes charge of two kinds of videos: ’The Collection of Silly Games’ and ’The Collection of Horrible Games’.
For simplicity’s sake, they will be called as videoA and videoB.
There are some people who want to watch videos during today, and they will be happy after watching videos of C-bacteria.
There are n hours a day, m videos are going to be show, and the number of people is K.
Every video has a type(videoA or videoB), a running time, and the degree of happi- ness after someone watching whole of it.
People can watch videos continuous(If one video is running on 2pm to 3pm and another is 3pm to 5pm, people can watch both of them).
But each video only allows one person for watching.
For a single person, it’s better to watch two kinds to videos alternately, or he will lose W happiness.
For example, if the order of video is ’videoA, videoB, videoA, videoB, …’ or ’B, A, B, A, B, …’, he won’t lose happiness; But if the order of video is ’A, B, B, B, A, B, A, A’, he will lose 3W happiness.
Now you have to help people to maximization the sum of the degree of happiness.

 

Input

Multiple query.
On the first line, there is a positive integer T, which describe the number of data. Next there are T groups of data.
for each group, the first line have four positive integers n, m, K, W : n hours a day, m videos, K people, lose W happiness when watching same videos).
and then, the next m line will describe m videos, four positive integers each line S, T, w, op : video is the begin at S and end at T, the happiness that people can get is w, and op describe it’s tpye(op=0 for videoA and op=1 for videoB).
There is a blank line before each groups of data.
T<=20, n<=200, m<=200, K<=200, W<=20, 1<=S<T<=n, W<=w<=1000,
op=0 or op=1

 

Output

Your output should include T lines, for each line, output the maximum happiness for the corresponding datum.

 

Sample Input

 

2 10 3 1 10 1 5 1000 0 5 10 1000 1 3 9 10 0 10 3 1 10 1 5 1000 0 5 10 1000 0 3 9 10 0

 

Sample Output

 

2000 1990

 

Source

2018 Multi-University Training Contest 10

 

Recommend

chendu   |   We have carefully selected several similar problems for you:  6437 6436 6435 6434 6433 

思路: 可以转化成最小费用最大流来求,

首先建立一个超级源点和一个次源点,建立一个汇点,

1.从超级源点到次源点建一条 (k,0) 的边

2.从次源点到所有的电影未拆点,建一条(1,0)的边

3.电影到自己本身拆点建边(1,-hap);

4.电影之间建边,只在en<= st 的情况下建边,并且判断type不相同的情况。

5. 电影的拆点到汇点之间建边(1,0)

为什么可以这么做呢? 因为题目保证了每个电影的hap>=1 && >=w ,所以我们建负权边的话,所以肯定不会出现我去看一个电影,并且电影的边权为正。

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int inf =0x3f3f3f3f;
const int N =605;

struct Edge
{
    int u,v;
    int cap,flow;
    int cost;
};

struct MCMF
{
    int n,m,s,t;
    vector<Edge>edges;
    vector<int >G[N];
    int inq[N];
    int d[N];
    int p[N];
    int a[N];
    void init(int n)
    {
        this->n=n;
        for(int i=0; i<=n+2; i++)
        {
            G[i].clear();
        }
        edges.clear();
    }

    void adde(int u,int v,int cap,int cost)
    {
        edges.push_back((Edge){u,v,cap,0,cost});
        edges.push_back((Edge){v,u,0,0,-cost});
        m=edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }

    bool spfa(int s,int t,int &flow,int &cost)
    {
        for(int i=0; i<=n+2; i++)d[i]=inf;
        memset(inq,0,sizeof(inq));
        d[s]=0;
        inq[s]=1;
        p[s]=0;
        a[s]=inf;
        queue<int >q;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            inq[u]=0;
            for(int i=0; i<G[u].size(); i++)
            {
                Edge &e=edges[G[u][i]];
                if(e.cap>e.flow&&d[e.v]>d[u]+e.cost)
                {
                    d[e.v]=d[u]+e.cost;
                    p[e.v]=G[u][i];
                    a[e.v]=min(a[u],e.cap-e.flow);
                    if(!inq[e.v])
                    {
                        q.push(e.v);
                        inq[e.v]=1;
                    }
                }
            }
        }
        if(d[t]==inf) return 0;
        flow+=a[t];
        cost+=d[t]*a[t];
        int u=t;
        while(u!=s)
        {
            edges[p[u]].flow+=a[t];
            edges[p[u]^1].flow-=a[t];
            u=edges[p[u]].u;
        }
        return 1;
    }

    void mincost_maxflow(int s,int t,int& flow,int & cost)
    {
        flow=0;
        cost=0;
        while(spfa(s,t,flow,cost));
    }

} a;

struct node
{
    int st,en,ha,type;
} aa[N];

int n,m,k,W;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d %d",&n,&m,&k,&W);
        a.init(2*m+5);
        for(int i=1; i<=m; i++)
        {
            scanf("%d %d %d %d",&aa[i].st,&aa[i].en,&aa[i].ha,&aa[i].type);
        }

        int yuan=2*m+1;
        int hui=2*m+2;
        a.adde(0,yuan,k,0);

        for(int i=1; i<=m; i++)
        {
            a.adde(yuan,i,1,0);
        }

        for(int i=1; i<=m; i++)
        {
            a.adde(i,i+m,1,-aa[i].ha);
        }
        for(int i = 1; i <= m; i++ )
        {
            for(int j = 1; j <= m; j++ )
            {
                if(i == j)continue;
                if(aa[i].en <= aa[j].st)
                {
                    a.adde(i + m, j, 1, (aa[i].type == aa[j].type ? W : 0));
                }
            }
        }

        for(int i=1; i<=m; i++)
        {
            a.adde(i+m,hui,1,0);
        }

        int flow,cost;
        flow=cost=0;
        a.mincost_maxflow(0,hui,flow,cost);
        cost=-cost;
        printf("%d\n",cost);
    }
    return 0;
}

这个题还有一个比较好的建图方案就是题解给的方法,我可以对两种不同类型的电影建立两条主链,节点间的边权为(INF,0)表示在休息,对于每一场电影,我们向对方链建一条边权为(1,hap)的边权,然后对于自己的链建一条边权为(1,hap-W) 的边,然后跑个最大花费就可以了。

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int inf =0x3f3f3f3f;
const int N =2000;
int n,m,K,W;

struct Edge
{
    int u,v;
    ll cap,flow;
    ll cost;
};

struct MCMF
{
    int n,m,s,t;
    vector<Edge>edges;
    vector<int >G[N];
    int inq[N];
    int p[N];
    ll d[N];
    ll a[N];
    void init(int n)
    {
        this->n=n;
        for(int i=0; i<=n+2; i++)
        {
            G[i].clear();
        }
        edges.clear();
    }

    void adde(int u,int v,ll cap,ll cost)
    {
        edges.push_back((Edge){u,v,cap,0,cost});
        edges.push_back((Edge){v,u,0,0,-cost});
        m=edges.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }

    bool spfa(int s,int t,ll &flow,ll &cost)
    {
        for(int i=0; i<=n+2; i++)d[i]=-inf;
        memset(inq,0,sizeof(inq));
        d[s]=0;
        inq[s]=1;
        p[s]=0;
        a[s]=inf;
        queue<int >q;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            //cout<<"u "<<u<<endl;
            q.pop();
            inq[u]=0;
            for(int i=0; i<G[u].size(); i++)
            {
                Edge &e=edges[G[u][i]];
                //cout<<"&&&&  "<<e.v<<endl;
                if(e.cap>e.flow&&d[e.v]<d[u]+e.cost)
                {
                    d[e.v]=d[u]+e.cost;
                    p[e.v]=G[u][i];
                    a[e.v]=min(a[u],e.cap-e.flow);
                    if(!inq[e.v])
                    {
                        q.push(e.v);
                        inq[e.v]=1;
                    }
                }
            }
        }
        if(d[t]==-inf) return 0;
        return 1;
    }

    void mincost_maxflow(int s,int t,ll& flow,ll & cost)
    {
        flow=0;
        cost=0;
        while(spfa(s,t,flow,cost))
        {
            flow+=a[t];
            cost+=d[t]*a[t];
            int u=t;
            while(u!=s)
            {
                edges[p[u]].flow+=a[t];
                edges[p[u]^1].flow-=a[t];
                u=edges[p[u]].u;
            }
        }
    }

} a;

int main()
{
    int T;
    int st,en,hap,type;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d %d",&n,&m,&K,&W);
        a.init(610);
        int SS=0; int CS=2*n+1; int TT=2*n+2;
        for(int i=1;i<n;i++){
            a.adde(i,i+1,inf,0);
            a.adde(i+n,i+n+1,inf,0);
        }

        a.adde(SS,CS,K,0);
        a.adde(CS,1,inf,0);
        a.adde(CS,1+n,inf ,0);
        a.adde(2*n,TT,inf,0);
        a.adde(n,TT,inf,0);

        int inode=2*n+2;

        for(int i=1;i<=m;i++){
            scanf("%d %d %d %d",&st,&en,&hap,&type);
            int tmp=++inode;
            if(type==0){
                a.adde(st,tmp,1,0);
                a.adde(tmp,en,1,hap-W);
                a.adde(tmp,en+n,1,hap);
            }
            else{
                a.adde(st+n,tmp,1,0);
                a.adde(tmp,en+n,1,hap-W);
                a.adde(tmp,en,1,hap);
            }
        }

        ll flow,cost;
        a.mincost_maxflow(SS,TT,flow,cost);
        printf("%lld\n",cost);
    }
    return 0;
}

/*

1
10 3 1 10
1 5 1000 0
5 10 1000 1
3 9 10 0

1
10 3 1 10
1 5 1000 0
5 10 1000 0
3 9 10 0

*/

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/81983331