码迷,mamicode.com
首页 > 其他好文 > 详细

Yali 19 - 8 - 6 test T2 猪国(pig) 题解

时间:2019-08-08 00:42:21      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:ack   国家   bit   namespace   标准   拓扑   注意   拓扑序   没有   

T2 猪国

题?描述

猪国是?个由 \(n\) 个城市组成的国家。
国王意识到了“要致富,先修路”这句话的重要性,它决定?规模修路。不巧的是,猪国的
猪们不太会?程,于是只能请隔壁鸡国的鸡建狂魔来帮忙修路。鸡建狂魔看不起猪,于是随
便建设了 \(m\) 条单向的路。尽管如此,每条路还是产?了或多或少的价值。
路修好了,经济却上不来。国王经过调研,发现了道路的巨?缺陷。具体来说,猪?们?向
感不好,?旦存在若?条路能组成?个环,那么可怜的猪?就有可能在环??绕来绕去,这
样甚?会产?反效果。
国王认为这不good。它决定改进这些路使得路再也不能组成环,这样就很good。
国王找到了鸡建狂魔要求售后服务,但鸡建狂魔只答应把若?条路反向,同时还要求收取费
?。国王不??被任意宰割,经过谈判,总费?为被反向的路的价值的最?值。
鸡建狂魔保证有办法使路变得good。国王想知道把路变得good的最?费?。当然,如果这
些路本来就很good,那么说明国王的调研有问题,?然费?就是 0。

输?格式

第??两个整数 \(n, m\)分别表?城市的数?和道路的数?。
接下来 ?,每?三个整数\(x , y , z\)表?这是?条从$ x \(城市单向到\) y \(城市的路,它的价值为\) z $。

输出格式

???个整数表?答案。

样例

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

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

数据范围
对于 30% 的数据,n,m <= 20 。
对于 60% 的数据,n,m <= 100 。
对于 100% 的数据,2 <= n, m < 1e5,1 <= x, y <= n, 1 <= z <= 1e9。
数据有梯度。

首先,我们看到出题人很(mo)(ming)(qi)(miao)的题解。

?分答案。把所有边权?于当前?分值的边拿出来建?个图。
有环就不?,否则就可以(?边都从拓扑序?点的连向拓扑序?的,?定没有环)。

但事实上,博主的思路是这样的。(事实上是一样的)

二分答案出一个值(data)(注意,这里的data是“被反向的路的价值的最?值”),边权大于这个data的边都不能动(边权小于data的您随意捣鼓)。于是乎就用这些不能动的边造一张图。好嘛,图造好了,拓扑一下,如果叼出来一个环,那显然不符合pig king的要求,那么就得吧data往上升,卡掉环内的一些边。(因为你想让这个图变成一个DAG,你至少得把这个图给摧毁)。哟,升多了,还得降。这样慢慢二分刨刨出来的data,就一定是最合适的data.这样做的话,时间复杂度是O(n log n),没问题

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int maxm = 1e5 + 5;
// n , m 的范围。
struct edge{int to, z;};
vector <edge> e[maxn];
// vector 存图
struct group{int u,v,w;}g[maxm];
// 用struct保存每一条边,以便二分时不断建图。
int n, m, x, y, z, cnt, ans;
//ans 是 最终的 data
void init(){
    for(int i = 1;i <= n;i ++){
        e[i].clear();
    }
}
//每次建图之前需要清零
bool work(int limit){
    //拓扑排序
    queue <int> q;
    int rd[maxn] = {0}, dot = 0;
    //dot是拓扑确定顺序的点数的数量
    init();
    for(int i = 1;i <= m;i ++){
        if(g[i].w > limit){
            e[g[i].u].push_back((edge){g[i].v,g[i].w}); 
            rd[g[i].v] ++;
        }
    }
    //建图
    for(int i = 1;i <= n;i ++){
        if(rd[i] == 0){
            dot ++;
            q.push(i);
        }
    }
    while(!q.empty()){
        int x = q.front();
        q.pop();
        for(int i = 0;i < e[x].size(); i ++){
            int y = e[x][i].to;
            rd[y] --;
            if(rd[y] == 0){
                q.push(y);
                dot ++;
            }
        }
    }
    //标准的topsort过程
    return dot == n;
    //如果图中有环,那么有些点显然是无法确定顺序的,自然dot != n
}
int main(){
    scanf("%d%d", &n, &m);
    for(int i = 1;i <= m;i ++){
        scanf("%d%d%d", &x, &y, &z);    
        g[++ cnt] = (group){x,y,z};
        //记录边数
    }
    int l = 0, r = 1e9;
    //二分data
    while(l <= r){
        int mid = l + r >> 1;//当前data
        if(!work(mid)){//如果当前data都爆出了环,那更小的data您就别想了
            l = mid + 1;
        } else {
            //如果可以的话,那就再更苛刻的范围内求data
            r = mid - 1;
            ans = mid;
        }
    }
    cout << ans;
    return 0;
}

Yali 19 - 8 - 6 test T2 猪国(pig) 题解

标签:ack   国家   bit   namespace   标准   拓扑   注意   拓扑序   没有   

原文地址:https://www.cnblogs.com/yangxuejian/p/11318598.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!