E - Andrew and Taxi-二分答案-topo判环

E - Andrew and Taxi

思路 :min max   明显二分答案,二分需要破坏的那些边的中机器人数量最多的那个。

check 过程建边时直接忽略掉小于 mid 的边,这样去检验有无环存在即可。 当时有一点担心会出现

有一个环 有一条边 反过来之后 这个环破坏了 却成就了 另一个环,但是画图发现 这样的图 ,它们两边会形成

一个大环。那个大环一定会通过别的边破坏掉,所以不需要担心这种情况。topo 判环即可。

#include<bits/stdc++.h>
using namespace std;
#define maxn 1234567
int n,m,head[maxn],ord[maxn],id;
int cnt,u,v,w,in[maxn],l,r,s;
vector<int>p;
struct data
{
    int u,v,w;
} e[maxn];
struct node
{
    int to,v,w;
} edge[maxn];
void add(int u,int v,int w)
{
    edge[++cnt].v=v;
    edge[cnt].to=head[u];
    edge[cnt].w=w;
    head[u]=cnt;
    in[v]++;
}
void topo(int x)
{
    id=cnt=0;
    queue<int>q;
    while(!q.empty())q.pop();
    for(int i=0; i<=n; i++)
    {
        head[i]=-1;
        ord[i]=in[i]=0;
    }
    for(int i=0; i<m; i++)
        if(e[i].w>x)add(e[i].u,e[i].v,e[i].w);
    for(int i=1; i<=n; i++)
    {
        if(in[i]==0)
        {
            q.push(i);
            ord[i]=++id;
        }
    }
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        for(int i=head[u]; i!=-1; i=edge[i].to)
        {
            v=edge[i].v;
            in[v]--;
            if(in[v]==0)
            {
                q.push(v);
                ord[v]=++id;
            }
        }
    }
}
bool ok(int x)
{
    topo(x);
    if(id<n)return false;
    return true;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0; i<m; i++)
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    r=1e9;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(ok(mid))r=mid-1;
        else l=mid+1;
    }
    topo(l);
    for(int i=0; i<m; i++)
        if(ord[e[i].u]>ord[e[i].v])
            p.push_back(i+1);
    s=p.size();
    printf("%d %d \n",l,s);
    for(int i=0; i<s; i++)
    {
        printf("%d",p[i]);
        if(i<s)printf(" ");
        else printf("\n");
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/SDUTNING/p/10265684.html

时间: 2024-07-31 07:33:28

E - Andrew and Taxi-二分答案-topo判环的相关文章

BZOJ 1486: [HNOI2009]最小圈( 二分答案 + dfs判负圈 )

二分答案m, 然后全部边权减掉m, 假如存在负圈, 那么说明有平均值更小的圈存在. 负圈用dfs判断. --------------------------------------------------------------------------- #include<bits/stdc++.h> #define rep(i, n) for(int i = 0; i < n; ++i) #define clr(x, c) memset(x, c, sizeof(x)) #define

CF-1100E Andrew and Taxi

CF-1100E Andrew and Taxi https://codeforces.com/contest/1100/problem/E 知识点: 二分 判断图中是否有环 题意: 一个有向图,每边有一条边权,对于一个值x,可以使得边权小于等于x的边反转,求最小的x,使得某些边反转之后图中没有环 分析:Suppose we have k traffic controllers. They can turn all edges whose weight is less than or equal

Gym 100886J Sockets 二分答案 + 贪心

Description standard input/outputStatements Valera has only one electrical socket in his flat. He also has m devices which require electricity to work. He's got n plug multipliers to plug the devices, the i-th plug multiplier has ai sockets. A device

SDUT 2778-小明的花费预算(二分答案)

小明的花费预算 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 小明终于找到一份工作了,但是老板是个比较奇怪的人,他并不是按照每月每月的这样发工资,他觉得你想什么时候来取都可以,取的是前边连续几个月中没有取的工资,而小明恰好是一个花钱比较大手大脚的人,所以他希望每次取得钱正好够接下来的n个月的花费. 所以让你把这n个月分成正好m组.每个组至少包含一个月,每组之中的月份必须是连续的,请你为他分组,使得分得的组中最大的总花费最小.

poj1743 后缀数组+二分答案

1.给定一个字符串,求最长重复子串,这两个子串可以重叠. 这道题是后缀数组的一个简单应用.做法比较简单,只需要求 height 数组里的最大值即可.2.给定一个字符串,求最长重复子串,这两个子串不能重叠. 这题比上一题稍复杂一点.先二分答案,把题目变成判定性问题:判断是否存在两个长度为 k 的子串是相同的,且不重叠.解决这个问题的关键还是利用height 数组.把排序后的后缀分成若干组,其中每组的后缀之间的 height 值都不小于 k.例如,字符串为“aabaaaab ” ,当 k=2 时,后

【BZOJ1305】dance跳舞(最大流,裂点,二分答案)

题意:一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲. 有一些男孩女孩相互喜欢,而其他相互不喜欢(不会"单向喜欢").每个男孩最多只愿意和k个不喜欢的女孩跳舞,而每个女孩也最多只愿意和k个不喜欢的男孩跳舞. 给出每对男孩女孩是否相互喜欢的信息,舞会最多能有几首舞曲? n<=50,k<=30 思路:明显的最大流问题 将每个男,女都裂成两个点,一个表示喜欢,另一个表示不喜欢 二分答案 (S,num

Educational Codeforces Round 21 Problem F (Codeforces 808F) - 最小割 - 二分答案

Digital collectible card games have become very popular recently. So Vova decided to try one of these. Vova has n cards in his collection. Each of these cards is characterised by its power pi, magic number ci and level li. Vova wants to build a deck

【笔记】二分答案

二分答案 O(nlogm) 对一段有序的序列 每次二分,从而快速的查找.解决的问题常是"使最大值最小"或"使最小值最大". 注意:①注意二分的序列是有序的,对于无序的序列进行二分需要先排序. ②二分的区间尽可能大(给定区间左右端点+-1) ③根据题目要求,设定好check函数. ④防止死循环.↓ 模板: 1 //第一种 2 while(r-1>l) 3 { 4 int mid=(l+r)>>1; 5 if(check(mid)) l=mid; 6

【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型

最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那个模型的但是我觉得他会不是一个圈我就否掉了,但是仔细想想的话会发现,如果是这样的话所得到的答案一定小于等于一个圈的答案(浓度),所以我们可定会得到最终答案,所以这样做是可以的,所以说要有宽松得正解的意识(泥沙俱下但沙子不影响我泥).当时我否掉最小割以后就立马去想费用流了,然后想到建图后发现那样建图虽