HDU5638 / BestCoder Round #74 (div.1) 1003 Toposort 线段树+拓扑排序
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是字典序最小的那个拓扑序列.
3
4 2 0
1 2
1 3
4 5 1
2 1
3 1
4 1
2 3
2 4
4 4 2
1 2
2 3
3 4
1 4
30
27
30
题解:
参考下普通的用堆维护求字典序最小拓扑序, 用某种数据结构维护入度小于等于kk的所有点, 每次找出编号最小的, 并相应的减少kk即可.
这个数据结构可以用线段树, 建立一个线段树每个节点[l,r][l,r]维护编号从ll到rr的所有节点的最小入度, 查询的时候只需要在线段树上二分, 找到最小的xx满足入度小于等于kk.
复杂度O((n+m)\log n)O((n+m)logn)
/// #include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include<vector>
using namespace std;
using namespace std ;
typedef long long ll;
#define mem(a) memset(a,0,sizeof(a))
#define pb push_back
const int N=+;
const int mod = 1e9+;
const int inf = 1e9+; int ind[N],head[N],t,n,m,K,vis[N];
vector<int > ans;
vector<int >G[N];
struct ss {
int l,r,sum,index;
}tr[N*];
struct sss {
int to,next;
}e[N*];
void init() {
t=;mem(head);mem(ind);ans.clear();mem(vis);
for(int i=;i<N;i++)G[i].clear();
}
void add(int u,int v) {e[t].to=v;e[t].next=head[u];head[u]=t++;}
void build(int k,int s,int t) {
tr[k].l=s;tr[k].r=t;
if(s==t) {
tr[k].sum=ind[s];
tr[k].index=s;
return ;
}
int mid=(s+t)>>;
build(k<<,s,mid);
build(k<<|,mid+,t);
tr[k].sum=min(tr[k<<].sum,tr[k<<|].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)>>;
if(tr[k<<].sum<=c) {
ret=ask(k<<,s,mid,c);
}
else {
ret=ask(k<<|,mid+,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)>>;
if(x<=mid) update(k<<,x,c);
else update(k<<|,x,c);
tr[k].sum=min(tr[k<<].sum,tr[k<<|].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=;i<=m;i++) {
scanf("%d%d",&u,&v);
ind[v]++;
G[u].pb(v);
}
build(,,n);
for(int i=;i<=n;i++) {
check=ask(,,n,K);
ans.pb(check);
K-=ind[check];
update(,check,inf);
for(int j=;j<G[check].size();j++) {
update(,G[check][j],-);
ind[G[check][j]]--;
}
}
ll A = ;
for(int i=;i<ans.size();i++) {
A=(A+1ll*(i+)*ans[i])%mod;
}
printf("%I64d\n",A);
}
return ;
}
HDU5638 / BestCoder Round #74 (div.1) 1003 Toposort 线段树+拓扑排序的更多相关文章
- hdu5635 BestCoder Round #74 (div.2)
LCP Array Accepts: 131 Submissions: 1352 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 13 ...
- hdu 5636 搜索 BestCoder Round #74 (div.2)
Shortest Path Accepts: 40 Submissions: 610 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: ...
- DP BestCoder Round #50 (div.2) 1003 The mook jong
题目传送门 /* DP:这题赤裸裸的dp,dp[i][1/0]表示第i块板放木桩和不放木桩的方案数.状态转移方程: dp[i][1] = dp[i-3][1] + dp[i-3][0] + 1; dp ...
- Codeforces Round #603 (Div. 2) E. Editor 线段树
E. Editor The development of a text editor is a hard problem. You need to implement an extra module ...
- Codeforces Round #660 (Div. 2) Captain Flint and Treasure 拓扑排序(按照出度、入读两边拓扑排序)
题目链接:Captain Flint and Treasure 题意: 一种操作为 选一个下标 使得ans+=a[i] 且 把a[b[i]]+a[i] 要求每个下标都进行一种这样的操作,问怎么样的 ...
- BestCoder Round #74 (div.2)
组合 1001 LCP Array 第一题就小难,出题的好像是浙大的大牛? 找到一个规律:a[i] = x, s[i..i+x]都想同.a[i] = a[i+1] + 1 (a[i] > 0), ...
- BestCoder Round #81 (div.2) 1003 String
题目地址:http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=691&pid=1003题意:找出一个字符串满足至少 ...
- BestCoder Round #50 (div.1) 1003 The mook jong (HDU OJ 5366) 规律递推
题目:Click here 题意:bestcoder 上面有中文题目 分析:令f[i]为最后一个木人桩摆放在i位置的方案,令s[i]为f[i]的前缀和.很容易就能想到f[i]=s[i-3]+1,s[i ...
- hdu 5637 BestCoder Round #74 (div.2)
Transform Accepts: 7 Submissions: 49 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072 ...
随机推荐
- centos下yum安装lamp和lnmp轻松搞定
centos下yum安装lamp和lnmp轻松搞定.究竟多轻松你看就知道了.妈妈再也不操心不会装lamp了. 非常辛苦整理的安装方法,会持续更新下去.凡无法安装的在评论里贴出问题来,会尽快解决.共同维 ...
- 【为小白菜打call】
作为本校的竞赛生,我必须为我大OJ打call caioj,小白菜oj,顾名思义,就是为刚踏进OI的“小白菜”们准备的网站,里面包含了许多专题内容,各种模版和讲解视频 而且对于刚学习C++的同学,更有帮 ...
- php匿名函数和可变参数函数
php匿名函数和可变参数函数 简介 直接上代码了: <?php $test1 = function($value) { echo $value; }; $test1('HelloWorld'); ...
- Linux平台Oracle多个实例启动说明
环境说明:oracle实例1的SID为orcl(为默认启动的实例),第二个实例的SID为orcl2 启动步骤: 1)启动数据库实例完成后,启动数据库监听服务 #lsnrctl start 2)切 ...
- 【POJ 2352】 Stars
[题目链接] http://poj.org/problem?id=2352 [算法] 树状数组 注意x坐标为0的情况 [代码] #include <algorithm> #include ...
- [MySQL] 按年度、季度、月度、周、日统计查询
该死的mysql没有提供unix时间戳的专门处理函数,所以,如果遇到时间分组,而你用的又是整型unix时间戳,则只有转化为mysql的其他日期类型! FROM_UNIXTIM()将unix时间戳转 ...
- Android Fragment RecycleListView
1.新建SuperActivity package com.example.ting.criminalintentpractise; import android.os.Bundle;import a ...
- 「JavaSE 重新出发」05.01.01 equals 方法
equals 方法示例 // 代码来自<Java核心技术 卷I>P167 // 父类 public class Employee{ ... public boolean equals(Ob ...
- CentOS 7.5安装pycharm
环境 安装环境: windows 10 Pro CentOS Linux release 7.6.1810 (Core) VMWare Workstation 15 Pro 安装图形化界面包 首先更新 ...
- HDU-2955 Robberies 浮点数01背包 自变量和因变量位置互换
题目链接:https://cn.vjudge.net/problem/HDU-2955 题意 突然想找几个银行抢钱. 给出各银行的钱数和被抓的概率,以及能容忍的最大被抓概率. 问他最多能抢到多少钱? ...