现在的位置: 首页 > 综合 > 正文

试题安排

2013年10月23日 ⁄ 综合 ⁄ 共 1672字 ⁄ 字号 评论关闭

试题安排

源程序名   arrange.???(pas|c|cpp)

输入文件名 arrange.in

输出文件名 arrange.out

时间限制   1s/testcase

空间限制   32MB

 

- 问题描述

给省队选拔赛命题的时候,李老师手下有N个命题人,要命N种不同类型的试题,其中每人命一题。因为每个命题人对不同题型的掌握程度不同,所以他们编出的试题难度也有不同(这用一个难度数值来表示)。为了尽可能地刁难大家,李老师决定出一张N个题的试卷,而且所有题的难度值总和最大。

 

- 输入数据

第一行为N(N <= 100),代表命题人的个数。

以后N行,每行N个整数(每个数不超过100),第i行j列的数表示第i个人出的第j种题目的难度大小。

 

- 输出数据

一行,表示试卷难度的最大值。

 

- 样例输入

3

50  50  1

10  100 10

100 10  10

 

- 样例输出

201

评测数据下载:http://download.csdn.net/detail/yuyanggo/5384199

解法:

首先,根据样例可以知道,每个老师出的题中仅选一道(如果可以选多道或不选,那就是大水题了)。

我们可以这样理解,将原问题抽象成一个二分图,n个老师在一边,n道题在另一边,在老师 i 与题目 j 之间连边,边值为 i 号老师出的 j 号题的难度。就可以将原问题抽象成求一个二分图的最大权匹配。这种问题可以用km算法或网络流,这里我就只讲网络流的做法。

如果不会最小费用最大流的话,请先自学再来接着往下看。如果你已经会最小费用最大流的话,那么最大费用最大流想必你也可以理解了。二分图的最大权匹配,实际上就可以用最大费用最大流来做,最大费用就是最大权。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;

int n,ed,map[210][210];
int dist[210],pre[210],q[210*5];
bool v[420],g[210][210];

void init()
{
  freopen("arrange.in","r",stdin);
  freopen("arrange.out","w",stdout);
}

void readdata()
{
  memset(g,0,sizeof(g));
  scanf("%d",&n);
  int i,j;
  for(i=1;i<=n;i++)
    for(j=n+1;j<=n+n;j++)
      scanf("%d",&map[i][j]),map[j][i]=-map[i][j],g[i][j]=1;
          
  for(i=1;i<=n;i++)map[0][i]=map[i][0]=0,g[0][i]=1;
  for(i=n+1,ed=n*2+1;i<ed;i++)map[i][ed]=map[ed][i]=0,g[i][ed]=1;    
}

inline bool spfa()
{
  memset(dist,-20,sizeof(dist));
  memset(pre,-1,sizeof(pre));
  memset(v,0,sizeof(v));
  int l=1,r=1,k,i;    
  q[1]=0,v[0]=1,dist[0]=0;
  while(l<=r)
    {
      k=q[l];l++;
      for(i=1;i<=ed;i++)
        if(g[k][i] && dist[i]<dist[k]+map[k][i])
          {
            dist[i]=dist[k]+map[k][i];
            pre[i]=k;
            if(!v[i])q[++r]=i,v[i]=1;
          }
      v[k]=0;
    }
  if(dist[ed]==dist[209])return 0;
  return 1;  
}

void work()
{
  int maxcost=0,k;
  while(spfa())
    {
      maxcost+=dist[ed];
      for(k=ed;pre[k]!=-1;k=pre[k])
        g[pre[k]][k]-=1,g[k][pre[k]]+=1;
    }
  printf("%d\n",maxcost);  
}

int main()
{
  init();
  readdata();
  work();
  return 0;
}

抱歉!评论已关闭.