Course Selection CodeChef – RIN

Course Selection CodeChef – RIN

大家好,又见面了,我是全栈君。

All submissions for this problem are available.

Read problems statements in Mandarin Chinese and Russian.

Rin is attending a university.

She has M semesters to finish her program, and that program has N required courses. Each course must be taken in exactly one of the semesters.

Some courses have prerequisites: for each i from 1 to K, she must take course A[i]before course B[i].

The same course may be taught by different professors in different semesters, and how well she does will depend on which professor teaches her. Additionally, some courses may not be taught every semester.

We are given an array X representing this information. For each course i and each semester j, X[i][j] = -1 if course i is not taught in semester j. Otherwise, X[i][j] will be an integer between 0 and 100: the expected score Rin will get if she takes course i in semester j.

Rin may take any number of courses per semester, including none, as long as they are taught that semester and she has already taken any required prerequisite courses.

Help Rin to find the maximal average score she can get over her whole program.

Input

The first line contain 3 integers: N, M and K.

This is followed by N lines, each containing M integers. The jth integer on the ith line represents the value of X[i][j].

This is followed by K lines, each containing two integers: A[i] and B[i].

Output

Output one real number: the maximal average score, rounded to 2 digits after the decimal point.

Constraints

  • 1 ≤ M, N ≤ 100
  • 0 ≤ K ≤ 100
  • -1 ≤ X[i][j] ≤ 100
  • 1 ≤ A[i], B[i] ≤ N
  • For each i, A[i] ≠ B[i].
  • For different i and j, (A[i], B[i]) ≠ (A[j], B[j]).
  • We guarantee there exists a way to take these N courses in M semesters.

Subtasks

Subtask 1: (20 Points) A course can have at most 1 pre request course.

Subtask 2: (80 Points) Refer to constraints above

Example

Input 1:
3 2 2
70 100
100 80
100 90
1 2
1 3

Output 1:
80.00

Input 2:
4 5 4
20 -1 100 -1 -1
100 30 -1 -1 -1
100 -1 30 20 40
100 30 40 50 20
1 2
1 3
2 4
3 4

Output 2:
32.50

Explanation

Example case 1

The only way she can finish these 3 courses is: take course 1 in the first semester, then take courses 2 and 3 in the second semester. The average score is (70 + 80 + 90) / 3 = 80.00.

Example case 2

The optimal solution is: take course 1 in semester 1, course 2 in semester 2, course 3 in semester 3 and course 4 in semester 4.

EXPLANATION:

First, let’s ignore the dependencies. The answer is just the maximum grade per course in any of the semesters, which is trivial to compute but let’s put this in another perspective:

For each course, the best grade is 100 – (minimum grade we lose by picking one of the semesters).

To model this as a network flow graph, we do 4 things:

  1. Create a vertex for each pair (course i, semester j).
  2. Create a source vertex which is connected to the first semester of each course i by an edge with capacity 100 – grade(i, 1).
  3. For every semester j from 2 to M, connect the vertices of each course i from semester j-1 to j with capacity 100 – grade(i, j) or 100 if the course is not available (it’s the same as having grade 0, recall that it’s guaranteed there is a solution).
  4. Create a sink vertex and connect the last semester of each course to it, with infinite capacity.

Consider the following example with 3 courses and 3 semesters:

3 3
10 70 100
80 50 40
80 20 40

alt text

The corresponding graph is depicted in the above picture. The maximum flow is equal to the combined grade loss for all courses. We pick semester 3 for course 1 (zero loss), and semester 1 for courses 2 and 3 (loss 20+20). The maximum grade average we can get is (N * 100 – maxflow) / N. In this case: (3*100 – 40) / 3 ~= 86.67.

– Returning to the problem, why does this help?

If we model the problem this way, we can also include the course dependencies. Suppose there are dependencies 1->2 and 1->3. The best we can do is course 1 in semester 2 and courses 2 and 3 in semester 3 for (70+40+40)/3 average.

– If there are dependencies 1->2 and 1->3, then courses 2 and 3 can never be done in the first semester.

This implies that the minimum grade loss for courses 2 and 3 is not bounded by its grades in semester 1. This is the same as changing the capacities associated to semester 1 of courses 2 and 3 to infinity.

– Why do we pick semester j for course 1?

The combined grade loss of doing course 1 in semester 2 + courses 2 and 3 in semester 3 is less than doing course 1 in semester 1 + courses 2 and 3 in semesters 2 or 3.

In terms of network flow, this means that

  • if we pick semester j = 1, then courses 2 and 3 are not bounded by grade loss in semester 1. To combine the grade loss by picking semester 1, we connect vertex (course 1, semester 1) to (course 2, semester 2) and (course 3, semester 2) with infinite capacity.
  • if we pick semester j = 2, then courses 2 and 3 are not bounded by grade loss in semesters 1 and 2. Same as above but connecting (course 1, semester 2) to courses 2 and 3, semester 3.
  • picking semester j = 3 is not possible.

The resulting network is the following

Course Selection CodeChef - RIN

We can see that the maximum flow is 150. The best is to distribute the grade loss of course 1 in semester 2, flow 3, among courses 2 and 3 in semester 3. In fact, 70+40+40 = 300 – 150.

To give you another example, consider the input

3 3 2
10 50 100
80 90 40
80 40 70
1 2
1 3

The best we can do course 1 at semester 1 (10) + course 2 at semester 2 (90) and course 3 at semester 3 (70) = 10+90+70. The resulting graph is

alt text

We can see that the maximum flow is 130 because in this case, it is better to distribute the grade loss of course 1 at semester 1, the flow 90, among the grade loss of courses 2 and 3 over semesters 2 and 3, respectively.

In a nutshell, we create a graph with N*M+2 vertices and use a standard maximum flow algorithm. The hard part was to realize how to build the network correctly.

Proof sketch:

Since max-flow equals min-cut, we can think of our problem as of finding a minimum cut in the above graph. Let Pi be a path corresponding to i-th course, i.e. the path formed of edges corresponding to i-th course in all semesters. In order to prove the correction of the above construction, we can show two properties of the graph:

  1. For every 1 <= i <= N, min-cut contains exactly one edge from Pi.
  2. For every constraint (i, j), if min-cut contains the k-th edge of Pi, then it contains the x-th edge of Pj, where x > k i.e. j-th course is taken in later semester than i-th course.

These two fact can be shown quite easily, but we will omit exact proofs here. Intuitively, if you pick any edge from Pi, then Pi is disconnected and there is no need for taking any other edge from it. Moreover, an edge (i, j) corresponding to a constraint, prevent us of taking course j before course i, because if you did it, then in order to make the graph disconnected, you would have to add the second edge of Pj to min-cut which contradicts the first fact.

Select Code
#include<cstdio>
#include<cstring>
#include<iostream>
#define inf 2e9
using namespace std;
const int Z=101;
const int N=Z*Z;
const int M=2e6+5;
struct edge{
   
   int v,next,cap;}e[M];int tot=1,head[N];
int n,m,k,cnt,ans,S,T,id[Z][Z],X[Z][Z],dis[N],q[M];
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){
   
   if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void add(int x,int y,int z){
	e[++tot].v=y;e[tot].cap=z;e[tot].next=head[x];head[x]=tot;
	e[++tot].v=x;e[tot].cap=0;e[tot].next=head[y];head[y]=tot;
}
inline bool bfs(){
	for(int i=S;i<=T;i++) dis[i]=-1;
	int h=0,t=1;q[t]=S;dis[S]=0;
	while(h!=t){
		int x=q[++h];
		for(int i=head[x];i;i=e[i].next){
			if(e[i].cap&&dis[e[i].v]==-1){
				dis[e[i].v]=dis[x]+1;
				if(e[i].v==T) return 1;
				q[++t]=e[i].v;
			}
		}
	}
	return 0;
}
int dfs(int x,int f){
	if(x==T) return f;
	int used=0,t;
	for(int i=head[x];i;i=e[i].next){
		if(e[i].cap&&dis[e[i].v]==dis[x]+1){
			t=dfs(e[i].v,min(e[i].cap,f));
			e[i].cap-=t;e[i^1].cap+=t;
			used+=t;f-=t;
			if(!f) return used;
		}
	}
	if(!used) dis[x]=-1;
	return used;
}
inline void dinic(){
	while(bfs()) ans-=dfs(S,inf);
}
inline int getY(int x){
	if(~x) return 100-x;
	return inf;
}
int main(){
	n=read();m=read();k=read();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			X[i][j]=read();
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			id[i][j]=++cnt;
		}
	}
	S=0,T=n*m+1;
	for(int i=1;i<=n;i++){
		add(S,id[i][1],getY(X[i][1]));
		for(int j=2;j<=m;j++) add(id[i][j-1],id[i][j],getY(X[i][j]));
		add(id[i][m],T,inf);
	}
	for(int i=1,a,b;i<=k;i++){
		a=read();b=read();
		add(S,id[b][1],inf);
		for(int j=2;j<=m;j++) add(id[a][j-1],id[b][j],inf);
	}
	ans=100*n;
	dinic();
	printf("%.2lf",1.0*ans/n);
	return 0;
}

 

转载于:https://www.cnblogs.com/shenben/p/6624196.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108595.html原文链接:https://javaforall.net

(0)
上一篇 2022年3月2日 上午10:00
下一篇 2022年3月2日 上午10:00


相关推荐

  • 上下文无关文法

    上下文无关文法1 上下文无关文法定义 文法 它描述语言语法结构的一组形式规则 上下文无关文法 它定义的语法范畴 或语法单位 是完全独立于这种范畴可能出现的环境 例如 在程序设计语言中 当碰到一个算术表达式时 我们完全可以 就事论事 处理 而不必考虑它所处的上下文 然而 在自然语言中 随便一个词 甚至一个字的意思在不同的上下文中都有可能有不同的意思 幸运的是 当今的程序设计语言都是上下文无关的

    2026年3月20日
    3
  • C程序编译过程浅析

    前几天看了《程序员的自我修养——链接、装载与库》中的第二章“编译和链接”,主要根据其中的内容简单总结一下C程序编译的过程吧。我现在一般都是用gcc,所以自然以GCC编译hellworld为例,简单总

    2021年12月25日
    55
  • 苹果新旧手机数据转移_换机必备知识:如何将数据转移到Oppo手机上

    苹果新旧手机数据转移_换机必备知识:如何将数据转移到Oppo手机上现在的智能手机越来越便宜了,换手机是经常的事情。但唯一的缺点是更换手机时新旧手机的数据备份很麻烦。许多人会选择将数据传输到计算机,然后再传输到新手机。或者,用户将可以备份的内容备份到microSD卡上。但这些方法都比较老土。如今,智能手机制造商拥有专用的应用程序,可以使此过程变得轻松,高效和无缝。本指南将教您如何将所有个人数据(SMS,电话,应用程序,照片等)从旧手机转移到Oppo品牌的手机上。…

    2022年5月25日
    228
  • java多线程–同步锁、

    java多线程–同步锁、同步代码块:语法:synchronized(同步锁){     需要同步操作的代码}—————————————————同步锁:为了保证每个线程都能正常执行原子操作,Java引入了线程同步机制.同步监听对象/同步锁/同步监听器/互斥锁:对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁….

    2022年6月13日
    30
  • numba 让python速度提升百倍

    numba 让python速度提升百倍本文仅供学习交流使用 如侵立删 联系方式及 demo 下载见文末 python 由于它动态解释性语言的特性 跑起代码来相比 java c 要慢很多 尤其在做科学计算的时候 十亿百亿级别的运算 让 python 的这种劣势更加凸显 办法永远比困难多 numba 就是解决 python 慢的一大利器 可以让 python 的运行速度提升上百倍 什么是 numba numba 是一款可以将 python 函数编译为机器代码的 JIT 编译器 经过 numba 编译的 python 代码 仅限数组运算 其运行速度可以接近 C 或 FORTRAN 语言

    2026年3月19日
    2
  • python能开发arm_获得通用技能的方法

    python能开发arm_获得通用技能的方法看了很多资料介绍如何将python移植到嵌入式设备当中,但总感觉杂乱五章,还移植不成功,但是经过我的多方摸索,成功的探索出了一条阳光大道,供各位网友借鉴参考。我采用的方法可以成功移植python2.7以后的所有版本。第一步:从官网下载源码.并把解压放在/opt第二步:在/Python-3.4.5目录下新建一键移植脚本,并执行内容如下:(执行完会报错某某模块内没安装,这个不耽误,…

    2022年10月10日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号