HDU 6437 【网络流-最小费用最大流】

Problem L.Videos

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

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


题意:一群人看电视,电视节目有一个播放的时间段,每个人都看电视,如果他连续看了相同类型的节目的话,开心值会减少 w,但是只要看了就会获得该节目的开心值,(一个节目只能被获取一次开心值),一个人在同一时刻只能观看一个节目,即不能同时观看时间的相互交叉的节目,要求最大开心值

T组数据,每组输入 n m k w 表示 一天 n 个小时,m个节目,k个人,w值

然后输入每个节目的开始时间,结束时间,开心值,类型

思路:网络流

1.源点连接 k 个人,流量为 1,费用为 0

2.一个节目建立两个点,起点和终点,起点连向终点 流量 1,费用 -1 * 开心值,终点连向汇点,流量1,费用0

3.如果一个节目的起点大于另一个节目的终点,判断类型,相同则连边,流量1,费用 w,否正流量1,费用0

4.k个人连向所有节目的起点,流量1,费用0

5.所有节目的终点指向汇点,流量 1,费用0

然后跑最小费用最大流,结果 * -1

【小结】比赛的时候一直在想这个题,想偏了,一直往贪心上面想,没考虑网络流,数据量这么小,应该先考虑到网络流的,很裸了这道题。

【代码】


#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))

const int maxn = 2 * 1e5 + 5;
const int inf = 0x3f3f3f3f; // ¿ÉÓÃmemset

int n,m,k,w;
int cnt = 0,source,sink;
int head[maxn],dis[maxn],pre[maxn];
bool vis[maxn];

struct node{
	int u,v,w,c,nxt;
	node(){}
	node(int u,int v,int w,int c,int nxt):u(u),v(v),w(w),c(c),nxt(nxt){}
}e[maxn];

struct node2
{
    int s;
    int t;
    int w;
    int op;
}vidio[203];

struct video{
	int l,r,c,opt;
}vdo[maxn];

void add(int u,int v,int w,int c){
	e[cnt] = node(u,v,w,c,head[u]);
	head[u] = cnt++;
	e[cnt] = node(v,u,0,-c,head[v]);
	head[v] = cnt++;
}

void init(int m,int k){
	cnt = 0;
	mem(head,-1);
	source = 0;
	sink = 2 * m + k + 1;
}

bool spfa(){
	mem(vis,false);
	mem(dis,inf);
	dis[source] = 0;
	vis[source] = true;
	queue<int>q;
	q.push(source);
	while(!q.empty()){
		int u = q.front();
		q.pop();
		vis[u] = false;
		for(int i = head[u];i != -1;i = e[i].nxt){
			int v = e[i].v,w = e[i].w,c = e[i].c;
			if(w > 0 && ((dis[u] + c) < dis[v])){
				dis[v] = dis[u] + c;
				pre[v] = i;
				if(!vis[v]){
					q.push(v);
					vis[v] = true;
				}
			}
		}
	}
	return dis[sink] != inf;;
}

int MinCostMaxFlow(){
	int full = 0;
	int cost = 0;
	while(spfa()){
		int minn = inf;
		for(int i = sink;i != source;i = e[pre[i]].u){
			minn = min(minn,e[pre[i]].w);
		}
		for(int i = sink;i != source;i = e[pre[i]].u){
			e[pre[i]].w -= minn;
			e[pre[i] ^ 1].w += minn;
		}
		cost += minn * dis[sink];
		full += minn;
	}
	return cost;
}

void getmap()
{
    for(int i=1;i<=k;i++)
    {
        add(0,i,1,0);
        for(int j=1;j<=m;j++)
        {
            add(i,k+j,1,0);
        }
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&vidio[i].s,&vidio[i].t,&vidio[i].w,&vidio[i].op);
        add(k+i,k+i+m,1,(-1)*vidio[i].w);
        add(k+i+m,k+2*m+1,1,0);
    }
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(vidio[i].t<=vidio[j].s)
            {
                if(vidio[i].op!=vidio[j].op)
                {
                    add(k+m+i,k+j,1,0);
                }
                else
                {
                    add(k+m+i,k+j,1,w);
                }
            }
        }
    }
}

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d %d %d",&n,&m,&k,&w);
		init(m,k);
		getmap();
		printf("%d\n",MinCostMaxFlow()*-1);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Destinymiao/article/details/82054626