E - E CodeForces - 1100E

一个n个节点的有向图,节点标号从1到n,存在m条单向边。每条单向边有一个权值,代表翻转其方向所需的代价。求使图变成无环图,其中翻转的最大边权值最小的方案,以及该方案翻转的最大的边权。

Input 单组输入,第一行包含两个整数n和m(2≤n≤100 000,1≤m≤100 000) 接下来m行,每行3个整数,u_i ,v_i

,w_i (1<= u_i , v_i <= n, 1<= w_i <=

10^9),表示u到v有一条权值为w的道路。道路编号从1开始。没有自环。

Output 在第一行中输出两个整数,即要翻转的最大的边权,和需要反转道路数量k。k不需要是最小的。

在下一行输出k个由空格分隔的整数,表示需要翻转的道路编号

如果有许多解决方案,请打印其中任何一个。

Examples
Input
5 6
2 1 1
5 2 6
2 3 2
3 4 3
4 5 5
1 5 4
Output
2 2
1 3
Input
5 7
2 1 5
3 2 3
1 3 3
2 4 1
4 3 5
5 4 1
1 5 3
Output
3 3
3 4 7

思路

  • 题意:给我一个有向带权值的图,这个图可能存在环,问所需改变的反转的边的最小权全是多少?
  • 思路:首先用二分枚举,要反转边的最大边权的最小值mid,都一个所给的图中的边中 边权小于mid 把这个边视为双向边(不存在),然后在剩下的子图中 跑一边 拓扑排序, 看是否有环的存在,如果有的话让 让 l = mid + 1, 否则 r = mid - 1
  • 链接



题解

#include<iostream>
#include<cmath>
#include<cstdio>
#include<queue>
#include<cstring>
#define int long long
#define inf 10000000000000
using namespace std;
int read(){
int res=0;char ch=0;
while (!isdigit(ch))ch=getchar();
while (isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res;
} const int N=1000100;
struct EDGE{
int ver,nxt,dis,pre;
}edge[N];
int n,m,cnt,head[N],vis[N],d[N],ans[N],dfn[N],dfs_cnt; void add(int u,int v,int t){
edge[++cnt].ver=v;
edge[cnt].nxt=head[u];
edge[cnt].dis=t;
edge[cnt].pre=u;
head[u]=cnt;
} queue<int>q;
bool check(int x){ memset(d,0,sizeof(d));memset(vis,0,sizeof(vis)); for (int i=1;i<=m;i++)if(edge[i].dis>x)d[edge[i].ver]++; for (int i=1;i<=n;i++)if (!d[i])q.push(i); while (!q.empty()){ int u=q.front();q.pop(); for (int i=head[u];i;i=edge[i].nxt)
{
if (edge[i].dis<=x)continue; int v=edge[i].ver;d[v]--;if (!d[v])q.push(v);
}
} for (int i=1;i<=n;i++)if (d[i])return 0; return 1;
}
void solute(int x){
memset(d,0,sizeof(d));memset(vis,0,sizeof(vis)); for (int i=1;i<=m;i++)if(edge[i].dis>x)d[edge[i].ver]++;
for (int i=1;i<=n;i++)if (!d[i])q.push(i); while (!q.empty())
{
int u=q.front();q.pop();dfn[u]=++dfs_cnt; for (int i=head[u];i;i=edge[i].nxt)
{
if (edge[i].dis<=x)continue;
int v=edge[i].ver;d[v]--;if (!d[v])q.push(v);
}
} for (int i=1;i<=m;i++){
if (edge[i].dis<=x){
int u=edge[i].pre,v = edge[i].ver;
if (dfn[u]>dfn[v])ans[++cnt]=i;
}
}
}
signed main(){
n=read();m=read();
for (int i=1;i<=m;i++){
int x=read(),y=read(),t=read();add(x,y,t);
}
int l=0,r=inf;
while (l<r)
{
int mid=l+r>>1;
if (check(mid))
r=mid;
else
l=mid+1;
} cnt=0;
solute(r);
printf("%lld %lld\n",r,cnt);
for (int i=1;i<=cnt;i++){
printf("%lld ",ans[i]);
}
}

E - E CodeForces - 1100E(拓扑排序 + 二分)的更多相关文章

  1. Codeforces 1100E 拓扑排序

    题意及思路:https://blog.csdn.net/mitsuha_/article/details/86482347 如果一条边(u, v),v的拓扑序小于u, 那么(u, v)会形成环,要反向 ...

  2. CROC 2016 - Elimination Round (Rated Unofficial Edition) D. Robot Rapping Results Report 拓扑排序+二分

    题目链接: http://www.codeforces.com/contest/655/problem/D 题意: 题目是要求前k个场次就能确定唯一的拓扑序,求满足条件的最小k. 题解: 二分k的取值 ...

  3. CF思维联系--CodeForces -214C (拓扑排序+思维+贪心)

    ACM思维题训练集合 Furik and Rubik love playing computer games. Furik has recently found a new game that gre ...

  4. CodeForces - 721C 拓扑排序+dp

    题意: n个点m条边的图,起点为1,终点为n,每一条单向边输入格式为: a,b,c     //从a点到b点耗时为c 题目问你最多从起点1到终点n能经过多少个不同的点,且总耗时小于等于t 题解: 这道 ...

  5. Codeforces 645D Robot Rapping Results Report【拓扑排序+二分】

    题目链接: http://codeforces.com/problemset/problem/645/D 题意: 给定n个机器人的m个能力大小关系,问你至少要前几个大小关系就可以得到所有机器人的能力顺 ...

  6. National Property CodeForces - 875C (拓扑排序)

    大意: n个字符串, 每次操作选出一种字符全修改为大写, 求判断能否使n个字符串字典序非降. 建源点s, 汇点t, s与所有必须转大写的连边, 必须不转大写的与t连边. #include <io ...

  7. Codeforces 1159E 拓扑排序

    题意及思路:https://www.cnblogs.com/dd-bond/p/10859864.html 代码: #include <bits/stdc++.h> #define LL ...

  8. CodeForces - 1100E 二分+拓扑排序

    题意: 一个n个节点的有向图,节点标号从1到n,存在m条单向边.每条单向边有一个权值,代表翻转其方向所需的代价.求使图变成无环图,其中翻转的最大边权值最小的方案,以及该方案翻转的最大的边权. Inpu ...

  9. codeforces 645 D. Robot Rapping Results Report 二分+拓扑排序

    题目链接 我们可以发现, 这是一个很明显的二分+拓扑排序.... 如何判断根据当前的点, 是否能构造出来一个唯一的拓扑序列呢. 如果有的点没有出现, 那么一定不满足. 如果在加进队列的时候, 同时加了 ...

随机推荐

  1. JAVA有关位运算的全套梳理

    一.在计算机中数据是如何进行计算的? 1.1:java中的byte型数据取值范围 我们最开始学习java的时候知道,byte类型的数据占了8个bit位,每个位上或0或1,左边第一位表示符号位,符号位如 ...

  2. tfgan折腾笔记(三):核心函数详述——gan_loss族

    gan_loss族的函数有: 1.gan_loss: 函数原型: def gan_loss( # GANModel. model, # Loss functions. generator_loss_f ...

  3. 关于PHP命名空间的讨论

    什么是命名空间? 根据php.net官方翻译文档描述,命名空间是这样定义的: 什么是命名空间?从广义上来说,命名空间是一种封装事物的方法. 在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用 ...

  4. ggplot2(4) 用图层构建图像

    4.1 简介 qplot()的局限性在于它只能使用一个数据集和一组图形属性映射,解决这个问题的办法就是使用图层.每个图层可以有自己的数据集和图形属性映射,附加的数据元素可通过图层添加到图形中. 一个图 ...

  5. python3:input() 函数

    一.知识介绍: 1.input() 函数,接收任意输入,将所有输入默认为字符串处理,并返回字符串类型: 2.可以用作文本输入,如用户名,密码框的值输入: 3.语法:input("提示信息:& ...

  6. 【学习参考】Animate.css动画演示

    学习参考地址: http://www.dowebok.com/demo/2014/98/

  7. strongsan基本用法

    0x01 安装 ====> CentOS RPM安装 下载:https://pkgs.org/download/strongswanwget http://download-ib01.fedor ...

  8. java-打印流(新手)

    实例:1.直接输出到文件里面. import java.io.*; //打印流->保持数据原样性并且打印.(各种数据类型.) public class Dyl { public static v ...

  9. Java内部类的四种分类以及作用介绍

    内部类内容解析 内部类的区分 内部类分别有成员内部类.局部内部类.匿名内部类.静态内部类,接下来将分别介绍. 成员内部类 就是位于外部类成员位置的类.与外部类的属性.方法并列. 成员内部类作为外部类的 ...

  10. 最长公共前缀(py)

    编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...