CSL 的训练计划 二分+最短路
作者:互联网
链接:https://ac.nowcoder.com/acm/contest/551/G
来源:牛客网
题目描述
众所周知,CSL 是一个负责的集训队队长。为了让集训队的学弟们训练更加饱和,他根据每个人的能力,提出了 m 个题数要求。假如 CSL 认为 yiyi 比 xixi 强,那么如果 xixi 做了 a 题,那 CSL 会要求 yiyi 需要做至少 a+ri×ka+ri×k,其中 riri 是已知的常数。CSL 现在一共有 s 道题目可以分给大家,因为 CSL 马上就要考OS了,所以他不想再出其他题了,请问正整数 k 最大是多少。
输入描述:
第一行有三个整数 n, m, s,分别表示集训队的学弟数量,CSL 的题数要求和 CSL 的题目数量。
接下来 m 行,每行三个整数 xi,yi,rixi,yi,ri,含义题目描述中所述。
2≤n≤2⋅1052≤n≤2⋅105
1≤m≤6⋅1051≤m≤6⋅105
1≤s≤10121≤s≤1012
1≤xi,yi≤n1≤xi,yi≤n
0≤ri≤1060≤ri≤106
输出描述:
在一行输出一个整数表示 k 可取的最大值。特别地,如果题目不够分则输出 0;为无穷大输出 -1。
示例1
输入
4 5 19 1 3 0 3 4 4 1 4 2 1 3 2 2 4 1
输出
2
示例2
输入
5 5 6 5 4 2 3 2 1 3 5 3 2 4 4 5 2 1
输出
0
题解:二分枚举答案,l 从1开始就可以了,因为不符合也是输出0,r设为s,若s时也符合则k可以无穷大了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define mk make_pair
const int N=2e5+10;
vector<pair<int,int> > v[N];
int n,m;
ll s,dp[N];
int in[N],vis[N];
bool judge(ll x)
{
queue<int> q;
ll ans=0;
for(int i=1;i<=n;i++)
{
vis[i]=0;
dp[i]=0;
if(!in[i])
{
q.push(i);
vis[i]=1;
}
}
int now;
pair<int,int> tmp;
// cout<<x<<endl;
while(!q.empty())
{
now=q.front();q.pop();
vis[now]=0;
for(int i=0;i<v[now].size();i++)
{
tmp=v[now][i];
if(dp[tmp.first] < dp[now] + tmp.second * x)
{
ans=ans-dp[tmp.first]+dp[now]+tmp.second*x;
if(ans>s) return 0;
dp[tmp.first]=dp[now]+tmp.second*x;
// cout<<tmp.first<<" "<<dp[tmp.first]<<endl;
if(!vis[tmp.first])
{
q.push(tmp.first);
vis[tmp.first]=1;
}
}
}
}
return 1;
}
int main()
{
scanf("%d%d%lld",&n,&m,&s);
int x,y,rr;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&rr);
v[x].pb(mk(y,rr));
in[y]++;
}
ll ans=0;
ll l=1,r=s;
while(l<=r)
{
ll mid=(r+l)>>1;
if(judge(mid))
{
ans=mid;
l=mid+1;
}
else r=mid-1;
}
if(ans==s) ans=-1;
printf("%lld\n",ans);
return 0;
}
标签:二分,CSL,ll,输出,短路,ans,yi,ri 来源: https://blog.csdn.net/mmk27_word/article/details/88947333