题目传送门(内部题149)


输入格式

  每个测试点第一行为四个正整数$n,b,s,m$,含义如题目所述。
  接下来$m$行,每行三个非负整数$u,v,l$,表示从点$u$到点$v$有一条权值为$l$的有向边,数据保证图是强连通的,也就是任意两个点之间都可以互相走到。


输出格式

  对每组数据输出一行一个非负整数表示答案。


样例

样例输入1:

5 4 2 10
5 2 1
2 5 1
3 5 5
4 5 0
1 5 1
2 3 1
3 2 5
2 4 5
2 1 1
3 4 2

样例输出1:

13

样例输入2:

5 4 2 10
5 2 1
2 5 1
3 5 5
4 5 10
1 5 1
2 3 1
3 2 5
2 4 5
2 1 1
3 4 2

样例输出2:

24


数据范围与提示

  每个测试点$5$分,各个测试点数据范围如下:

  除此之外,数据中可能会均匀出现一些$s$值比较小的点。
  对于所有的测试点,均有$m\leqslant 50,000,1\leqslant s\leqslant b<n,0\leqslant l\leqslant 10,000$,给定的有向图合法且强连通。


题解

先求出每个点到总部的正反最短路,建反向边即可。

化一下式子即可发现每一个点的代价为它的正反最短路长度和乘上它所在子项目有几个分部$-1$。

利用贪心的思想,小的放在一起,大的放在一起一定更优,于是可以排个序。

接着考虑$DP$,设$dp[i][j]$表示选到$i$,分了$j$组的最小代价,但是发现时间复杂度是$\Theta(n^3)$的,接着考虑优化。

在最优解中$dis$从小到大依次划分得到的段的长度一定是单调不增的,所以只有$[i-\frac{i}{j},i)$才能更新$dp[i][j]$。

那么现在算法的时间复杂度就是:$\Theta(n^2(\frac{1}{1}+\frac{1}{2}+\frac{1}{3}+...+\frac{1}{n}))=\Theta(n^2\log n)$。

由于时限为$3s$所以跑过去绰绰有余。

时间复杂度:$\Theta(n^2\log n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to,w;}e[100001];
int head[2][5001],cnt;
int n,b,s,m;
int dis[2][5001];
bool vis[5001];
long long sum[5001],dp[5001][5001];
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
void add(bool id,int x,int y,int w)
{
e[++cnt].nxt=head[id][x];
e[cnt].to=y;
e[cnt].w=w;
head[id][x]=cnt;
}
void Dij0()
{
q.push(make_pair(0,b+1));
dis[0][b+1]=0;
while(q.size())
{
int x=q.top().second;q.pop();
if(vis[x])continue;vis[x]=1;
for(int i=head[0][x];i;i=e[i].nxt)
if(dis[0][e[i].to]>dis[0][x]+e[i].w)
{
dis[0][e[i].to]=dis[0][x]+e[i].w;
q.push(make_pair(dis[0][e[i].to],e[i].to));
}
}
}
void Dij1()
{
memset(vis,0,sizeof(vis));
q.push(make_pair(0,b+1));
dis[1][b+1]=0;
while(q.size())
{
int x=q.top().second;q.pop();
if(vis[x])continue;vis[x]=1;
for(int i=head[1][x];i;i=e[i].nxt)
if(dis[1][e[i].to]>dis[1][x]+e[i].w)
{
dis[1][e[i].to]=dis[1][x]+e[i].w;
q.push(make_pair(dis[1][e[i].to],e[i].to));
}
}
}
int main()
{
scanf("%d%d%d%d",&n,&b,&s,&m);
for(int i=1;i<=m;i++)
{
int a,b,l;
scanf("%d%d%d",&a,&b,&l);
add(0,a,b,l);add(1,b,a,l);
}
memset(dis,0x3f,sizeof(dis));
Dij0();Dij1();
for(int i=1;i<=b;i++)
sum[i]=dis[0][i]+dis[1][i];
sort(sum+1,sum+b+1);
for(int i=1;i<=b;i++)sum[i]+=sum[i-1];
memset(dp,0x3f,sizeof(dp));
dp[0][0]=0;
for(int i=1;i<=b;i++)
for(int j=1;j<=s;j++)
for(int k=i-i/j;k<i;k++)
{
if((sum[i]-sum[k])*(i-k-1)>=dp[i][j])break;
dp[i][j]=min(dp[i][j],dp[k][j-1]+(sum[i]-sum[k])*(i-k-1));
}
printf("%lld",dp[b][s]);
return 0;
}

rp++

[CSP-S模拟测试]:任务分配(最短路+贪心+DP)的更多相关文章

  1. [CSP-S模拟测试]:二叉搜索树(DP+贪心)

    题目传送门(内部题99) 输入格式 第一行一个整数$n$,第二行$n$个整数$x_1\sim x_n$. 输出格式 一行一个整数表示答案. 样例 样例输入: 58 2 1 4 3 样例输出: 数据范围 ...

  2. [CSP-S模拟测试]:C(三分+贪心)

    题目传送门(内部题46) 输入格式 第一行$3$个整数$n,m,t$.第二行$n$个整数,表示$P_i$.接下来$m$行每行两个整数,表示$L_i,R_i$. 输出格式 一行一个整数表示答案. 样例 ...

  3. [CSP-S模拟测试]:括号密码(贪心)

    题目描述 在“无限神机”的核心上,有一个奇怪的括号密码,密码初始已经有一个括号序列,有$n$个限制条件,每个限制条件描述为$l_i$和$r_i$,表示区间$[l_i,r_i]$的括号序列必须合法.调整 ...

  4. [CSP-S模拟测试]:trade(反悔贪心)

    题目传送门(内部题62) 输入格式 第一行有一个整数$n$.第二行有$N$个整数:$a_1\ a_2\ a_3\cdot\cdot\cdot a_n$. 输出格式 一行一个整数表示最大收益. 样例 样 ...

  5. [CSP-S模拟测试]:Graph(图论+贪心)

    题目描述 给定一张$n$个点$m$条边的无向图,每条边连接两个顶点,保证无重边自环,不保证连通你想在这张图上进行若干次旅游,每次旅游可以任选一个点$x$作为起点,再走到一个与 $x$直接有边相连的点$ ...

  6. [CSP-S模拟测试]:虎(DFS+贪心)

    题目传送门(内部题15) 输入格式 第一行一个整数$n$,代表点数接下来$n-1$行,每行三个数$x,y,z$,代表点$i$与$x$之间有一条边,若$y$为$0$代表初始为白色,否则为黑色,若$z$为 ...

  7. [CSP-S模拟测试]:Emotional Flutter(贪心)

    题目传送门(内部题51) 输入格式 第一行一个整数$t$表示数据组数.每组数据的第一行有三个整数$s,k,n$.第二行有$n$个整数$A_1,A_2,...,A_n$,依次表示黑白条的长度. 输出格式 ...

  8. 联赛模拟测试25 C. Repulsed 贪心+树形DP

    题目描述 分析 考虑自底向上贪心 \(f[x][k]\) 表示 \(x\) 下面距离为 \(k\) 的需要灭火器的房间数,\(g[x][k]\) 表示 \(x\) 下面距离为 \(k\) 的多余灭火器 ...

  9. [CSP-S模拟测试]:字符交换(贪心+模拟)

    题目传送门(内部题136) 输入格式 输入文件第一行为两个正整数$n,k$,第二行为一个长度为$n$的小写字母字符串$s$. 输出格式 输出一个整数,为对字符串$s$进行至多$k$次交换相邻字符的操作 ...

随机推荐

  1. bash 中的 :=、=、:-、-、=?、?、:+、+

    bash 中的 :=.=.:-.-.=?.?.:+.+ 来源 https://www.cnblogs.com/fhefh/archive/2011/04/22/2024750.html 变量替换和变量 ...

  2. 服务端相关知识学习(六)Zookeeper client

    Zookeeper的client是通过Zookeeper类提供的.前面曾经说过,Zookeeper给使用者提供的是一个类似操作系统的文件结构,只不过这个结构是分布式的.可以理解为一个分布式的文件系统. ...

  3. javascript相关的增删改查以及this的理解

    前两天做了一个有关表单增删改查的例子,现在贴出来.主要是想好好说一下this. 下面贴一张我要做的表格效果. 就是实现简单的一个增删改查. 1.点击增加后自动增加一行: 2.点击保存当前行会将属性改成 ...

  4. 常用的Java工具类——十六种

    常用的Java工具类——十六种 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选 ...

  5. 【Spring Cloud】 总结

    一.Spring Cloud简介 简单来说,Spring Cloud 就是致力于分布式系统.微服务等的一套在目前非常火热的框架.但它的本身也是一系列框架的有序集合(由多个模块组成). 相比较于Dubb ...

  6. 7.Struts2拦截器及源码分析

    1.Struts2架构图 2.Struts2 执行过程分析 1.首先,因为使用 struts2 框架,请求被Struts2Filter 拦截 2.Struts2Filter  调用 DisPatche ...

  7. 开源you-get项目爬虫,以及基于python+selenium的自动测试利器

    写在前面 爬虫和自动测试,对于python来说是最合适不过也是最擅长的. 开源的项目也很多,例如you-get项目https://github.com/soimort/you-get.盗链和爬虫神器. ...

  8. cmake 判断操作系统平台

    转载自 cmake 判断操作系统平台 MESSAGE(STATUS "operation system is ${CMAKE_SYSTEM}") IF (CMAKE_SYSTEM_ ...

  9. 5.Nginx的session一致性(共享)问题配置方案1

    1:Session共享 为什么要实现共享,如果你的网站是存放在一个机器上,那么会话数据就在这台机器,但是如果你使用了负载均衡把请求分发到不同的机器呢?这个时候会话 id在客户端是没有问题的,但是如果用 ...

  10. Number of Parallelograms CodeForces - 660D (几何)

    Number of Parallelograms CodeForces - 660D You are given n points on a plane. All the points are dis ...