一天,玛莎在公园散步,发现树下有一张图……惊讶吗?你认为这个问题会有一些合乎逻辑和合理的故事吗?没门!所以,问题是……玛莎有一个有向图,第i个顶点包含一个正整数a。最初玛莎可以在某个顶点放一枚硬币。在第一个操作中,她可以将放置在某个顶点u上的硬币移动到任何另一个顶点v上,这样图形中就有一条有方向的边u→v。每次当硬币被放置在某个顶点i时,玛莎在她的笔记本上写下一个整数a(特别是当玛莎最初将硬币放在某个顶点时,她在笔记本上写下一个整数a)。玛莎想要做k -1个运算,这样她笔记本上的最大运算数就越小越好。输入第一行包含三个整数n, m和k (1 <n < 2-105,0 < m< 2- 105,1 < k < 1018) -图中的顶点和边的数量,以及Masha应该做的操作的数量。第二行包含n个整数a (1 < a <10°)——写在图顶点上的数字。下面的m行每一行都包含两个整数u和v (1 < u v < n)——这意味着在图中有一条边u→v。它保证了图不包含循环和多边。输出打印一个整数——玛莎在最佳硬币移动过程中在笔记本上写下的最大数字的最小值。如果玛莎不能执行k -1个操作,则输出-1。
Examples
input
Copy
6 7 4 1 10 2 3 4 5 1 2 1 3 3 4 4 5 5 6 6 2 2 5
output
Copy
4
input
Copy
6 7 100 1 10 2 3 4 5 1 2 1 3 3 4 4 5 5 6 6 2 2 5
output
Copy
10
input
Copy
2 1 5 1 1 1 2
output
Copy
-1
input
Copy
1 0 1 1000000000
output
Copy
1000000000
题解:
要我们求移动k - 1步并且移动步数中最大值最小 ,那我们直接二分枚举最值x即可
把权值小于x的点的边存入途中,然后拓扑排序,找最长边
有两个判断条件,如果最长边>=k说明x值太大,
如果一个点没走过,但是权值 <= x,并且入度不为0,说明存在环
都要r = mid - 1
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<set>
using namespace std;
#define int long long
const int N = 4e6 + 10;
typedef pair<int, int> PII;
int n,m,k;
vector<int> p[N];
struct node
{
int l,r;
}d[N];
int a[N];
int vis[N];
int in[N];
int check(int x)
{
for(int i = 1;i <= n;i++)
{
p[i].clear();
vis[i] = 0;
in[i] = 0;
}
for(int i = 1;i <= m;i++)
{
auto [u,v] = d[i];
if(a[u] <= x&& a[v] <= x )
{
p[u].push_back(v);
in[v]++;
}
}
queue<PII> q;
for(int i = 1;i <= n;i++)
{
if(in[i] == 0&&a[i] <= x)
{
q.push({i,1});
}
}
int mx = 0;
while(q.size())
{
auto t = q.front();
vis[t.first] = 1;
mx = max(mx,t.second);
q.pop();
for(auto it:p[t.first])
{
in[it]--;
if(in[it] == 0&&a[it] <= x)
{
q.push({it,t.second+1});
}
}
}
int f = 0;
for(int i = 1;i <= n;i++)
{
if(!vis[i] && a[i] <= x&&in[i]!=0)
{
f = 1;
}
}
if(mx >= k)
f = 1;
return f;
}
void solve()
{
cin >> n >> m >> k;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
}
for(int i = 1;i <= m;i++)
{
int x,y;
cin >> x >> y;
d[i] = {x,y};
}
int l = 1,r = 1e9;
while(l <= r)
{
int mid = (l + r)/2;
if(check(mid))
r = mid - 1;
else
l = mid + 1;
}
if(l == 1e9 + 1)
l = -1;
cout << l ;
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
// cin >> t;
//scanf("%lld",&t);
while (t--)
{
solve();
}
}
//3 F
//5 B
//6 F
//9 F
//10 B
//12 F
//15 FB
//18 FB