T2豚州
説明タイトル先の時間
ブタは⼀によって国です\(N \)構成国、都市。
王はサイズズーム道路を決定するのはこの文の重要性を、「最初の道路を建設、金持ちに」ということに気づきました。残念ながら、国の豚の
豚は⼯ない通常のプロセスを行うので、彼らは唯一の道路を構築するためにあなたの鶏の鶏まくる次の国を構築することができます。チキン工事まくるそうで、豚を軽蔑
それの建設\(m個\)一方向の道を。それにもかかわらず、すべての道路やアフター生産額多かれ少なかれ。
道路が建設された、経済が出てくることができました。研究を通じて王は、巨大なズーム欠陥道路を見つけました。ある⺠豚ことを具体的に、方向
、乾いた道路がある場合は、良い意味ではないが、⼀一度リング、リング⾥⾯を一周することが可能である⺠そして貧しい豚、⼀で構成することができ
、非常になっても同様⾄逆効果。
王は、これは良くないと考えています。それは、このような組成物は、もはやループ経路をすることができますので、それが良好であることを改善するためのパスを決定します。
王は鶏がアフターサービスの要件まくるを建てたが、鶏がいる場合のみ、乾いた道を逆にするだけでなく、有料課金することを約束しまくる建てられた見つけ
、それを適用することを。キング⽢センター加重交渉を通じて、トータルコストの使用のための値が最大値から道路の逆である、任意の慈悲ではありません。
チキンは、道路が良くなるようにする方法があることを確認しまくるを構築しました。王は良い⼩料使用になるための最善の方法を知りたいと思いました。場合はもちろん、
いくつかの方法が非常に優れているとされてい、そして王の研究の問題を説明し、自然な着色料の使用は0です。
START入力フォーマット
最初のフレーム⾏二つの整数\(N、Mの\)は、それぞれ、先の時間と都市道路の数を監視する宛先時間の数を示します。
次⾏は、各⾏三つの整数\(X、Y、Zの\ ) 表が表示され⼀X- $からこの記事\(市内\へ片道) Y-の\(都市の道路は、その値は\である)のZ $ 。
出力フォーマット
⼀⾏⼀整数テーブル表示の答え。
サンプル
入力1
5 6
2 1
5 2 6
2 3 2
3 4 3
4 5
1〜5 4
出力1
2
入力2
5
7
2 1 5
3 2 3
1 3 3
2 4 1
4 3 5
5 4 1
1 5 3
出力2
3
データの範囲は
、M <= 20、データの30%を、N。
データの60%を、N、M <= 100。
データの100%、2 <= N、M <へ 1e5,1 <= xと、Y <= N、1 <= Z <= 1E9。
傾斜データ。
まず第一に、我々は、人々は問題外であることがわかりモリブデン(Mo)持っています (明)道路 (チー) 理由(ミャオ族)問題への解決策。
⼆分の答え。電流側の全ての右端は⼆スコアをズームアウト⼀マップを構築します。
⾏環、又は(さえトポロジーから小ドットの配列順のトポロジーに⼩両側をズームリング⼀与えられていない)ことができるがありません。
しかし、実際には、アイデアは、このブロガーです。(実質的に同一)
二値答値(データ)、右側が移動することはできませんデータよりも大きくなっている一方で(右側はあなたがいじることは自由ですデータよりも小さい)、(ノートでは、ここではデータ「MAX値は、道路の逆の値である」です) 。これらは、図に可動側とすることができない以来。さて、図面をリングアウトディアオ場合、それは豚の王の要件に明らかに矛盾している、トポロジー、終了しました、それはデータを上昇しなければならない、オフカードリングでいくつかのエッジ。(この図は、DAGになりたいので、あなたは、少なくとも破壊するために、この数字を配置する必要があります)。ヨ、アップより、落下しなければなりませんでした。このような遅い半平面データプレーン出て、それはそう。最も適切なデータである必要があり、時間の複雑さはO(n個の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;
}