主要思路为连反向边。

对于本题,贪心策略,依次决定每个人的最优解

但因为每人达到的最优解可能有多种方式,如果每个都尝试就会超时,所以只能先采取其中一种

并将这个方案连反向边,其它方案连正向边

这样对于之后的人决策,可以看哪些导师能够走到汇点

就是反向建图后,从汇点BFS判断能到达哪些导师,再判断哪个更优。

例如:对于这个例子

建图为

先考虑选手1。 1,2号导师都能到达汇点,并且选择1,2号导师对于目前来说都是最优解(现在无法确定哪个对于之后更优),所以先选择1。

图变为

(红色为反向边)

考虑选手2。 1,2号导师都能到达汇点,1更优,所以选择1。这里走了反向边后走到了2导师,相当于让1选手选择2导师。

这个思想类似最大流的增广路算法(都是利用反向边来调整之前错误的决策)。

这道题有“前 i 名的录取结果最优,当且仅当在前 i − 1 名的录取结果最优的情况下:第 i 名 被其理论可能的最高志愿录取”这句话,这个属于贪心。这有这样,才能使用本题思想。

#include <stdio.h>
int fr[410],ne[5010],lad[410];
int v[5010],w[5010],bs=0;
int dl[410],la[410],n,m,sy[210];
bool bk[410],xz[210][210];
int zy[210][210],jg[210],yq[210];
void addb(int a,int b,int c)
{
v[bs]=b;
w[bs]=c;
ne[bs]=fr[a];
fr[a]=bs;
bs+=1;
}
void bfs()
{
for(int i=1;i<=n+m;i++)
bk[i]=false;
int he=0,ta=0;
for(int i=1;i<=m;i++)
{
if(sy[i]>0)
{
dl[ta]=i+n;
la[i+n]=-1;
bk[i+n]=true;
ta+=1;
}
}
while(he<ta)
{
for(int i=fr[dl[he]];i!=-1;i=ne[i])
{
if(w[i]>0&&!bk[v[i]])
{
bk[v[i]]=true;
dl[ta]=v[i];
la[v[i]]=i;
lad[v[i]]=dl[he];
ta+=1;
}
}
he+=1;
}
}
void jisuan()
{
for(int i=1;i<=n;i++)
{
bfs();
for(int j=1;j<=m;j++)
xz[i][j]=bk[n+j];
int t=-1;
for(int j=1;j<=m;j++)
{
if((bk[n+j]&&zy[i][j]>0)&&(t==-1||zy[i][j]<zy[i][t]))
t=j;
}
if(t==-1)
{
jg[i]=m+1;
continue;
}
jg[i]=zy[i][t];
int x=t+n;
while(1)
{
if(la[x]==-1)
{
sy[x-n]-=1;
break;
}
w[la[x]]-=1;
w[la[x]^1]+=1;
x=lad[x];
}
for(int j=1;j<=m;j++)
{
if(zy[i][j]==zy[i][t])
{
if(j==t)
{
addb(i,j+n,1);
addb(j+n,i,0);
}
else
{
addb(j+n,i,1);
addb(i,j+n,0);
}
}
}
}
}
int main()
{
int T,C;
scanf("%d%d",&T,&C);
while(T--)
{
bs=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n+m;i++)
fr[i]=-1;
for(int i=1;i<=m;i++)
scanf("%d",&sy[i]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
scanf("%d",&zy[i][j]);
}
for(int i=1;i<=n;i++)
scanf("%d",&yq[i]);
jisuan();
for(int i=1;i<=n;i++)
printf("%d ",jg[i]);
printf("\n");
for(int i=1;i<=n;i++)
{
int l=0,r=i;
while(l<r)
{
int mi=(l+r)>>1;
bool zd=false;
for(int j=1;j<=m;j++)
{
if(xz[i-mi][j]&&zy[i][j]!=0&&zy[i][j]<=yq[i])
{
zd=true;
break;
}
}
if(zd)
r=mi;
else
l=mi+1;
}
printf("%d ",l);
}
printf("\n");
}
return 0;
}

最新文章

  1. Git合并分支操作
  2. Jquery-input获取单选框选择的按钮
  3. 伸展树(三)之 Java的实现
  4. WeisEditor 3.2.1B 使用说明 [源码下载]
  5. 产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复
  6. 叠罗汉I
  7. 使用FTP删不掉文件的解决方法
  8. 取消jQuery validate验证
  9. HW5.19
  10. [Webpack 2] Maintain sane file sizes with webpack code splitting
  11. Codeforces Round #253 (Div. 2), problem: (B)【字符串匹配】
  12. asp.net 检查文件夹和文件是否存在
  13. List&lt;T&gt; 求差集
  14. OGG的孩子-有损音频编码opus
  15. Azure Storage用法:使用Blob Storage
  16. Python基础之数组和向量化计算总结
  17. CNN中feature map、卷积核、卷积核个数、filter、channel的概念解释,以及CNN 学习过程中卷积核更新的理解
  18. JDK1.7和JDK1.8对于异常的支持
  19. Python 输出格式符号
  20. 【python】内存调试

热门文章

  1. [DEBUG] Springboot打包jar/war后访问包外的路径
  2. Python——方法
  3. Manacher算法+注释
  4. sftp配置多个用户权限的问题
  5. centos系统基本操作命令
  6. 【php socket通讯】php实现http服务
  7. SVN 问题解决之 Working copy path does not exist in repository
  8. elementUI动态数据表格(带分页)
  9. SuperMemo method
  10. 判断对象是否为null