题意为给一张有向图,每条边有对应价格,Alice有一个初始金钱c,它可以从图中买一些边来构成一个新图
Bob每一次删除可以删除一些边的集合,条件是集合中不能有环,问Alice最多能让Bob删几次
首先我们稍微想象一下画个图就可以知道,任何一张图都可以拆成两张无环图组合在一起
因为可以在第一次时,把每个环都拿一条边出来,这样肯定不会构成环,又能保证第二次拿的时候没有环
也就是Bob最多删两次
问题就转换为Alice的钱能不能买到最小环
我们假设有两个点A,B,那么A->B 的最短路加上 B->A的最短路(前提是AB强连通)就是一个有关于AB的最小环
我们只要
遍历找出所有最小环中最小花费的那个即可
这题n是2000,可以跑n次dijkstra,求任意两点间最短路
最后答案就是
如果一条边都买不起,答案为0
如果买不起环,答案为1
否则答案为2
代码如下:
#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair<int,int>
#define et cout<<'\n'
#define xx first
#define yy second
using namespace std;
template <typename _Tp>void input(_Tp &x){
char ch(getchar());bool f(false);while(!isdigit(ch))f|=ch==45,ch=getchar();
x=ch&15,ch=getchar();while(isdigit(ch))x=x*10+(ch&15),ch=getchar();
if(f)x=-x;
}
template <typename _Tp,typename... Args>void input(_Tp &t,Args &...args){input(t);input(args...);}
const int inf=100000000000000000;
const int N=2005;
const int M=5005;
int dist[N][N];
int st[N];
vector<pll> v[N];
int n,m;
void dijkstra(int star){
fer(i,1,n){
dist[star][i]=inf;
st[i]=false;
}
dist[star][star]=0;
priority_queue<pll,vector<pll>,greater<pll> >heap;
heap.push({0,star});
while(heap.size()){
auto t=heap.top();
heap.pop();
int ver=t.second;
if(st[ver]) continue;
st[ver]=true;
for(auto t:v[ver]){
if(dist[star][t.first]>dist[star][ver]+t.second){
dist[star][t.first]=dist[star][ver]+t.second;
heap.push({dist[star][t.first],t.first});
}
}
}
}
signed main()
{
int sum;
input(n,m,sum);
bool fl=false;
fer(i,1,m){
int a,b,c;
input(a,b,c);
if(sum>=c) fl=true;
v[a].pb({b,c});
}
if(fl==false){
cout<<0<<'\n';
return 0;
}
int mn=inf;
fer(i,1,n){
dijkstra(i);
}
// fer(i,1,n){
// fer(j,1,n){
// cout<<dist[i][j]<<" ";
// }
// cout<<endl;
// }
fer(i,1,n){
fer(j,i+1,n){
if(dist[i][j]!=inf && dist[j][i]!=inf){
mn=min(mn,dist[i][j]+dist[j][i]);
}
}
}
if(sum>=mn){
cout<<2<<'\n';
}
else{
cout<<1<<'\n';
}
}