CF1100E Andrew and Taxi 二分答案+拓扑排序
\(\color{#0066ff}{ 题目描述 }\)
给定一个有向图,改变其中某些边的方向,它将成为一个有向无环图。
现在求一个改变边方向的方案,使得所选边边权的最大值最小。
\(\color{#0066ff}{输入格式}\)
点数n,边数m,接下来是m条有向边
\(\color{#0066ff}{输出格式}\)
输出一个最大值,一个k
接下来一行k个数,表示那些边需要反向
\(\color{#0066ff}{输入样例}\)
5 6
2 1 1
5 2 6
2 3 2
3 4 3
4 5 5
1 5 4
5 7
2 1 5
3 2 3
1 3 3
2 4 1
4 3 5
5 4 1
1 5 3
\(\color{#0066ff}{输出样例}\)
2 2
1 3
3 3
3 4 7
\(\color{#0066ff}{数据范围与提示}\)
\(2 \leq n \leq 100000\), \(1 \leq m \leq 100000\)
\(\color{#0066ff}{ 题解 }\)
根据题目,显然要二分答案
考虑二分答案之后怎么做
对于比mid大的边,我们肯定是不能改变方向的
于是直接加入图中
然后只需看看有没有环就行了,因为比mid小的边我们可以任意更改
可以用拓扑排序做
因为它只让最大值最小,并没有说改变边的数量最小,所以小的边随便改
现在考虑输出方案
我们在拓扑排序的时候记一下每个点的拓扑序
考虑一条边x到y,如果x的拓扑序大于y,显然可能成环(不是一定成环)
但是如果x的拓扑序小于y,一定不会成环
题目有不限制改边数量,我们就将其反向即可
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 1e5 + 10;
struct node {
int x, y, z, id;
friend bool operator < (const node &a, const node &b) {
return a.z < b.z;
}
}e[maxn];
struct E {
int to;
E *nxt;
E(int to = 0, E *nxt = NULL): to(to), nxt(nxt) {}
}pool[maxn], *tail;
int du[maxn], top[maxn];
bool vis[maxn];
int n, m;
E *head[maxn];
void add(int from, int to) {
head[from] = new E(to, head[from]);
}
bool ok(int mid) {
std::queue<int> q;
int cnt = 0;
tail = pool;
for(int i = 1; i <= n; i++) du[i] = 0, head[i] = NULL, top[i] = 0;
for(int i = 1; i <= m; i++) vis[i] = false;
for(int i = m; i >= 1; i--) {
if(e[i].z <= mid) break;
add(e[i].x, e[i].y);
du[e[i].y]++;
}
for(int i = 1; i <= n; i++) if(!du[i]) q.push(i);
while(!q.empty()) {
int tp = q.front(); q.pop();
top[tp] = ++cnt;
for(E *i = head[tp]; i; i = i->nxt) {
du[i->to]--;
if(!du[i->to]) q.push(i->to);
}
}
if(cnt != n) return false;
for(int i = 1; i <= m; i++) {
if(e[i].z > mid) break;
if(top[e[i].x] > top[e[i].y]) vis[e[i].id] = true;
}
return true;
}
int main() {
n = in(), m = in();
for(int i = 1; i <= m; i++) e[i].x = in(), e[i].y = in(), e[i].z = in(), e[i].id = i;
std::sort(e + 1, e + m + 1);
int l = 0, r = 1e9;
int ans = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if(ok(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
ok(ans);
int tot = 0;
for(int i = 1; i <= m; i++) if(vis[i]) tot++;
printf("%d %d\n", ans, tot);
for(int i = 1; i <= m; i++) if(vis[i]) printf("%d ", i);
return 0;
}
CF1100E Andrew and Taxi 二分答案+拓扑排序的更多相关文章
- CF1100E Andrew and Taxi
题目地址:CF1100E Andrew and Taxi 二分,每次取到一个 \(mid\) ,只保留长度 \(>mid\) 的边 dfs判环,若有环,说明 \(ans>mid\) ,否则 ...
- bzoj5280/luogu4376 MilkingOrder (二分答案+拓扑序)
二分答案建图,然后判环,就可以了. 字典序输出的话,只要做拓扑序的时候用优先队列来维护就可以了. (其实判环也可以用拓扑序...) #include<cstdio> #include< ...
- CF-1100 E Andrew and Taxi
CF-1100E Andrew and Taxi https://codeforces.com/contest/1100/problem/E 知识点: 二分 判断图中是否有环 题意: 一个有向图,每边 ...
- CF 1100E Andrew and Taxi(二分答案)
E. Andrew and Taxi time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- E. Andrew and Taxi(二分+拓扑判环)
题目链接:http://codeforces.com/contest/1100/problem/E 题目大意:给你n和m,n代表有n个城市,m代表有m条边,然后m行输入三个数,起点,终点,花费.,每一 ...
- CF #CROC 2016 - Elimination Round D. Robot Rapping Results Report 二分+拓扑排序
题目链接:http://codeforces.com/contest/655/problem/D 大意是给若干对偏序,问最少需要前多少对关系,可以确定所有的大小关系. 解法是二分答案,利用拓扑排序看是 ...
- 【CF645D】 Robot Rapping Results Report(拓扑排序,二分)
题意:有一张N点M边的有向图,求最小的K使根据前K条边就能够确定图是否有唯一的拓扑序, 若没有唯一拓扑序输出-1 思路:二分答案再拓扑排序,以入度为0的节点作为新的一层,若某一层的节点个数<&g ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) D. Robot Rapping Results Report 拓扑排序+二分
题目链接: http://www.codeforces.com/contest/655/problem/D 题意: 题目是要求前k个场次就能确定唯一的拓扑序,求满足条件的最小k. 题解: 二分k的取值 ...
- codeforces 645 D. Robot Rapping Results Report 二分+拓扑排序
题目链接 我们可以发现, 这是一个很明显的二分+拓扑排序.... 如何判断根据当前的点, 是否能构造出来一个唯一的拓扑序列呢. 如果有的点没有出现, 那么一定不满足. 如果在加进队列的时候, 同时加了 ...
随机推荐
- python第三十二天-----算法
算法(Algorithm):一个计算过程,解决问题的方法时间复杂度:用来评估算法运行效率的一个东西ps:在日常使用中,请使用sort(),because no zuo no die! 1.冒泡排序:指 ...
- O2O和B2C、C2C的区别
B2C.C2C是在线支付,购买的商品会塞到箱子里通过物流公司送到你手中;O2O是在线支付,购买线下的商品.服务,再到线下去享受服务. O2O模式的核心很简单,就是把线上的消费者带到现实的商店中去.在线 ...
- C Primer Plus学习笔记(八)- 函数
函数简介 函数(function)是完成特定任务的独立程序代码单元 使用函数可以省去编写重复代码的苦差,函数能让程序更加模块化,提高程序代码的可读性,更方便后期修改.完善 #include <s ...
- PowerDesigner中批量替换name和code的脚本
无论是cdm还是pdm都可以批量替换.处理.可在Tool-Execute commands-Edit/Run script中编辑运行脚本: 下面的脚本是批量将CDM中实体的用Code替换掉Name O ...
- linux下mysql 最新版安装图解教程
1.查看当前安装的linux版本 命令:lsb_release -a 如下图所示 通过上图中的数据可以看出安装的版本为RedHat5.4,所以我们需要下载RedHat5.4对应的mysql安装包 2. ...
- 11-09SQLserver 基础-数据库之汇总练习45题
设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表(四)所示,数据如表1-2的表 ...
- LAMP 3.3 mysql常用操作-1
有一个图形化管理 mysql 的工具叫做 phpmyadmin,如何在命令行下面来管理和操作 mysql. 首先进入mysql mysql -uroot -pwangshaojun 查看有那些库 &g ...
- C#log4net引入配置文件后,数据库连接找不到并且有很多 未能找到元素“appender”的架构信息
今天用了log4net加入配置信息后,数据库链接的字符串就报错,无法连接数据库.后来发现,只需要调整一下位置就可以了 configSections 节点必须写在 connectionStrings 节 ...
- mysql的安装以及简单的命令符
在百度当中输入mySQL就可以下载了. 我们只需要一路的点击next就好了,注意,我们在安装的过程当中它会问我们是否要安装路径,我么要选择是. 在显示安装完成之后呢,我们会看到一个复选框,上面写着是否 ...
- Windows系统上release版本程序bug跟踪解决方案-.dmp文件。
使用场景: Win32程序在release模式下编译完成,发送给最终用户使用时,我们的程序有时候也会出现崩溃的情况,这个时候如果能快速定位崩溃原因或提供一些程序崩溃时的状态信息,对我们解决问题将会带来 ...