• Codechef Course Selection


    Home » Practice(Hard) » Course Selection

    Course Selection Problem Code: RINSolvedSubmit

    https://www.codechef.com/problems/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.

    n个课程要在m个学期里完成,

    有k个依赖关系a,b ,表示a课程必须在b课程之前

    每个课程在每个学期有相应得分

    -1 表示本学期不开设此课程

    问 最大的课程得分平均值

    最大得分转化为最小扣分

    对下面这张图跑最小割,ans=n*100-最小割

    解释:       Step 4 :  inf边一定不会被割,a是b的前置课程,如果b的边割在了a之前,图可以通过inf边联通,不符合最小割

    求助大佬,为什么以下建图方式不对

    #include<queue>
    #include<cstdio>
    #include<algorithm>
    #define inf 0x7fffffff
    #define N 10101
    #define M 50000
    using namespace std;
    queue<int>q;
    int n,m,k,src,decc,tmp;
    int front[N],to[M],nxt[M],tot=1;
    int lev[N],cur[N],cap[M];
    int score[101][101];
    bool f[101];
    //#define turn((i),(j)) ((i)-1)*(m+1)+(j)
    int turn(int i,int j)
    {
        return (i-1)*m+j;
    }
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; 
    }
    bool bfs()
    {
        while(!q.empty()) q.pop();
        for(int i=src;i<=decc;i++) cur[i]=front[i],lev[i]=-1;
        lev[src]=0; q.push(src);
        int now;
        while(!q.empty())
        {
            now=q.front(); q.pop();
            for(int i=front[now];i;i=nxt[i])
            {
                if(lev[to[i]]==-1&&cap[i]>0)
                {
                    lev[to[i]]=lev[now]+1;
                    if(to[i]==decc) return true;
                    q.push(to[i]);
                }
            }
        }
        return false;
    }
    int dinic(int now,int flow)
    {
        if(now==decc) return flow;
        int rest=0,delta;
        for(int &i=cur[now];i;i=nxt[i])
        {
            if(lev[to[i]]>lev[now]&&cap[i]>0)
            {
                delta=dinic(to[i],min(flow-rest,cap[i]));
                if(delta)
                {
                    cap[i]-=delta; cap[i^1]+=delta;
                    rest+=delta; if(rest==flow) break;
                } 
            }
        }
        if(rest!=flow) lev[now]=-1;
        return rest; 
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        int x; decc=n*m+1;
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          scanf("%d",&score[i][j]);
        for(int i=1;i<=n;i++)   add(turn(i,m),decc,inf);
        int a,b;
        while(k--)
        {
            scanf("%d%d",&a,&b);
            for(int i=1;i<m;i++) add(turn(a,i),turn(b,i+1),inf);
            f[b]=true;
        }
        for(int i=1;i<=n;i++) 
         for(int j=1;j<=m;j++)
          if(j==1) 
           {
                 if(f[i]) add(src,turn(i,1),inf);
                 else  add(src,turn(i,1),score[i][j]==-1 ? inf : 100-score[i][j]);
           }
          else add(turn(i,j-1),turn(i,j),score[i][j]==-1 ? inf : 100-score[i][j]);
        while(bfs()) 
         tmp+=dinic(src,inf);
        tmp=n*100-tmp;
        printf("%.2lf",double(tmp)/n);
    }

    错误建图代码

    #include<queue>
    #include<cstdio>
    #include<algorithm>
    #define inf 0x7fffffff
    #define N 10101
    #define M 50000
    using namespace std;
    queue<int>q;
    int n,m,k,src,decc,tmp;
    int front[N],to[M],nxt[M],tot=1;
    int lev[N],cur[N],cap[M];
    //#define turn((i),(j)) ((i)-1)*(m+1)+(j)
    int turn(int i,int j)
    {
        return (i-1)*(m+1)+j;
    }
    void add(int u,int v,int w)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; cap[tot]=w;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; 
    }
    bool bfs()
    {
        while(!q.empty()) q.pop();
        for(int i=src;i<=decc;i++) cur[i]=front[i],lev[i]=-1;
        lev[src]=0; q.push(src);
        int now;
        while(!q.empty())
        {
            now=q.front(); q.pop();
            for(int i=front[now];i;i=nxt[i])
            {
                if(lev[to[i]]==-1&&cap[i]>0)
                {
                    lev[to[i]]=lev[now]+1;
                    if(to[i]==decc) return true;
                    q.push(to[i]);
                }
            }
        }
        return false;
    }
    int dinic(int now,int flow)
    {
        if(now==decc) return flow;
        int rest=0,delta;
        for(int &i=cur[now];i;i=nxt[i])
        {
            if(lev[to[i]]>lev[now]&&cap[i]>0)
            {
                delta=dinic(to[i],min(flow-rest,cap[i]));
                if(delta)
                {
                    cap[i]-=delta; cap[i^1]+=delta;
                    rest+=delta; if(rest==flow) break;
                } 
            }
        }
        if(rest!=flow) lev[now]=-1;
        return rest; 
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        int x; decc=n*(m+1)+1;
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          {
                scanf("%d",&x);
              if(x==-1) x=inf;
              else x=100-x;
              add(turn(i,j),turn(i,j+1),x);
          }
        for(int i=1;i<=n;i++) 
         add(0,turn(i,1),inf),
         add(turn(i,m+1),decc,inf);
        int a,b;
        while(k--)
        {
            scanf("%d%d",&a,&b);
            for(int i=1;i<=m;i++) add(turn(a,i),turn(b,i+1),inf);
        }
        while(bfs()) 
         tmp+=dinic(src,inf);
        tmp=n*100-tmp;
        printf("%.2lf",double(tmp)/n);
    } 
    View Code
  • 相关阅读:
    java操作html格式数据
    FineReport启动后访问404
    Linux环境安装配置JDK
    微信小程序-获取地理位置
    Redis模糊查询
    文件的上传与下载
    Java批量压缩下载
    Xcode7.x中安装Alcatraz
    环信其他设备登录返回登录界面
    UTF-8编码规则(转)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6882446.html
Copyright © 2020-2023  润新知