博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU5638 / BestCoder Round #74 (div.1) 1003 Toposort 线段树+拓扑排序
阅读量:5335 次
发布时间:2019-06-15

本文共 2273 字,大约阅读时间需要 7 分钟。

Toposort

 
问题描述
给出nn个点mm条边的有向无环图. 要求删掉恰好kk条边使得字典序最小的拓扑序列尽可能小.
输入描述
输入包含多组数据. 第一行有一个整数TT, 表示测试数据组数. 对于每组数据: 第一行包含3个整数nn, mm和kk (1 \le n \le 100000, 0 \le k \le m \le 200000)(1≤n≤100000,0≤k≤m≤200000), 表示图中结点数目, 图中边的数目以及要删的边数. 接下来mm行, 每行包含两个整数u_iui and v_ivi, 表示存在一条u_iui到v_ivi的有向边 (1 \le u_i, v_i \le n)(1≤ui,vi≤n). 输入保证给定的图是一个DAG. 输入数据中nn的和不超过10^6106. 输入数据中mm的和不超过2 \cdot 10^62⋅106.
输出描述
对于每组数据, 输出一个整数S = (\displaystyle\sum_{i=1}^{n}{i\cdot p_i}) \text{ mod } (10^9 + 7)S=(i=1∑ni⋅pi) mod (109+7), 其中p_{1}, p_{2}, ..., p_{n}p1,p2,...,pn是字典序最小的那个拓扑序列.
输入样例
34 2 01 21 34 5 12 13 14 12 32 44 4 21 22 33 41 4
输出样例
302730

 题解:

参考下普通的用堆维护求字典序最小拓扑序, 用某种数据结构维护入度小于等于kk的所有点, 每次找出编号最小的, 并相应的减少kk即可.

这个数据结构可以用线段树, 建立一个线段树每个节点[l,r][l,r]维护编号从ll到rr的所有节点的最小入度, 查询的时候只需要在线段树上二分, 找到最小的xx满足入度小于等于kk.

复杂度O((n+m)\log n)O((n+m)logn)

///1085422276#include 
#include
#include
#include
#include
#include
using namespace std;using namespace std ;typedef long long ll;#define mem(a) memset(a,0,sizeof(a))#define pb push_backconst int N=100000+50;const int mod = 1e9+7;const int inf = 1e9+7;int ind[N],head[N],t,n,m,K,vis[N];vector
ans;vector
G[N];struct ss { int l,r,sum,index;}tr[N*5];struct sss { int to,next;}e[N*20];void init() { t=1;mem(head);mem(ind);ans.clear();mem(vis); for(int i=0;i
>1; build(k<<1,s,mid); build(k<<1|1,mid+1,t); tr[k].sum=min(tr[k<<1].sum,tr[k<<1|1].sum);}int ask(int k,int s,int t,int c) { int ret; if(tr[k].l==tr[k].r&&tr[k].l==s) { return tr[k].index; } int mid=(tr[k].l+tr[k].r)>>1; if(tr[k<<1].sum<=c) { ret=ask(k<<1,s,mid,c); } else { ret=ask(k<<1|1,mid+1,t,c); } return ret;}void update(int k,int x,int c) { if(tr[k].l==tr[k].r&&tr[k].l==x) { tr[k].sum+=c; return ; } int mid=(tr[k].l+tr[k].r)>>1; if(x<=mid) update(k<<1,x,c); else update(k<<1|1,x,c); tr[k].sum=min(tr[k<<1].sum,tr[k<<1|1].sum);}int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&K); init();int u,v,check; for( int i=1;i<=m;i++) { scanf("%d%d",&u,&v); ind[v]++; G[u].pb(v); } build(1,1,n); for(int i=1;i<=n;i++) { check=ask(1,1,n,K); ans.pb(check); K-=ind[check]; update(1,check,inf); for(int j=0;j

 

转载于:https://www.cnblogs.com/zxhl/p/5245959.html

你可能感兴趣的文章
在公司最大的收获是什么
查看>>
html2image
查看>>
x64内核内存空间结构
查看>>
个人博客作业Week2(9月30日)
查看>>
二次样条差值算法
查看>>
xcode 配置系统环境变量 Preporocessing 预编译宏的另一种写法, 系统的DEBUG 由来
查看>>
解决FPDF报错:FPDF error: Not a JPEG file / FPDF error: Not a PNG file
查看>>
第三章 jQuery事件和动画
查看>>
可变数组继承不可变数组,添、删、改、查、替换
查看>>
对文本的读出和写入字符串操作
查看>>
application配置和profile隔离配置
查看>>
Ubuntu 12.04 中安装和配置 Java JDK
查看>>
Spark中RDD转换成DataFrame的两种方式(分别用Java和Scala实现)
查看>>
阿里云短信服务Java版
查看>>
读《Android深度探索(卷1)HAL与驱动开发》的一些思考05
查看>>
Django框架基础知识09-请求与响应
查看>>
修改服务中可执行文件的路径
查看>>
当Activity继承AppCompatActivity如何实现隐藏标题栏与状态栏
查看>>
web基础,用html元素制作web页面
查看>>
四种losses
查看>>