原题链接:Problem - 1679D - Codeforces
题意翻译
珂朵莉给了你一个有向图,点数为 n ,边数为 m ,每个点有一个点权 ,任选起点,走 k-1 步(即包括起点和终点总共 k 个点),问经过的所有点的最大权值的最小是多少?若无解输出 -1。
输入格式
第一行包含三个整数 n,m,k —— 表示图中顶点数,边的数量,以及珂朵莉应该执行的操作的数量。(,,,)
第二行包含 n 个整数 ——表示点的点权。
接下来的 m 行中的每一行都包含两个整数 u 和 v —— 意味着图中有一条边 u→v 。
有向图中没有重边和自环,但是可能会有环。
输出样例
思路
错误:一开始想暴力dfs,求出每一段长度 (1~k) 的最大值的最小值,就是vis[x]++ vis[x]-- ,后来发现不行。
正确:最大值的最小值,自然的想到 二分 ,根据题意来看,我们可以二分答案。
要判断一个答案 mid 可不可行,我们先枚举每个点,只留下点权小于等于 mid 的点(vis[i]=1),再枚举每条边,将我们选出来点集重新连成有向图。
现在我们只需要判断新建的图合不合法。
如果这张图有环,那答案显然成立。
若没有环,那我们就要求出这张图的最长路判断它是不是大于等于 k 。
找环,求有向无环图的最长路,这两个可以用拓扑排序同时做。
代码
#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define ll long long
#define fir first
#define sec second
#define rep(i,a,n) for(int i=a;i<n;i++)
#define endl "\n"
template <class...Args> void _(Args... args) {
auto _ = [&](auto x) {cout << x << " ";};
cout << "-->";
int arr[] = {(_(args), 0)...};
cout << endl;
}
const int N = 1e6 + 7;
const int mod = 1e9+7;
int n, m, mx, a[N], u[N], v[N], du[N], f[N], vis[N];
ll k;
vector<int> chu[N];
int check(int maxx){
for(int i=1;i<=n;i++){
chu[i].clear(); vis[i]=0; du[i]=0; f[i]=0;
} mx=0;
for(int i=1;i<=n;i++){
if(a[i]<=maxx) vis[i]=1;
}
for(int i=1;i<=m;i++){
if(vis[u[i]]&&vis[v[i]]){
chu[u[i]].push_back(v[i]);
du[v[i]]++;
}
}
queue<int> q;
for(int i=1;i<=n;i++){
if(du[i]==0&&vis[i]) q.push(i);
}
if(!q.empty()) mx=1; //_(q.size(),"*");
while(!q.empty()){
int t=q.front(); q.pop();
f[t]=1; mx=max(mx,vis[t]);
for(auto it:chu[t]){
du[it]--; vis[it]=max(vis[it],vis[t]+1);
if(du[it]==0) q.push(it);
}
}
//判断是否有环
int flag=0;
for(int i=1;i<=n;i++){
if(vis[i]&&!f[i]){
flag=1; break;
}
}
if(flag==0&&(ll)mx<k) return 0;
else return 1;
}
void solve() {
cin>>n>>m>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>u[i]>>v[i];
int st=1, ed=1e9, mid, ans=-1;
while(st<=ed){
mid=(st+ed)/2;
if(check(mid)){
ed=mid-1; ans=mid;
}else {
st=mid+1;
}
}
cout<<ans<<"\n";
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int Case=1;
while(Case--) solve();
return 0;
}
易错点
要单独给 k 开long long /(ㄒoㄒ)/~~