题意:总结一下就是求一个最小环,如果能够买下这个最小环,则需要删除两次,否则如果我能够买下一条边,则需要删除一次,否则如果我一条边都不能买下,则一次都不用删除
思路:用dijkstra求出来任意两个点之间的最短距离,然后枚举一下所有的边,不妨设a->b,价钱为c,则如果有环则一定是dist[b][a]+c,即从b到a的距离加上从a到b的距离,然后枚举一下所有的边统计一下最小的距离
如果用tarjan算法求强连通分量之后然后枚举所有的环,这样不能够保证枚举到最小的环,因为如果是这种情况的话,中间环可能回枚举不到,导致判断错误
一下是dijkstra求最小环
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int N=2e3+7,M=5e3+7;
typedef long long ll;
struct Node{
int a,b,c;
};
Node edge[M];
int n,m,C;
int h[N],e[M],ne[M],w[M],idx;
int dist[N][N];
bool st[N];
typedef pair<int,int> PII;
void add(int a,int b,int c) {
e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
inline int read() {
int f=1,c=0;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') f=f*-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
c=c*10+ch-'0';
ch=getchar();
}
return f*c;
}
void dijkstra(int i,int dist[]) {
memset(dist,0x3f,N*4);
memset(st,false,sizeof st);
priority_queue<PII,vector<PII>,greater<PII> > q;
dist[i]=0;
q.push({dist[i],i});
while(q.size()) {
auto t=q.top();
q.pop();
int ver=t.second,dis=t.first;
if(st[ver]) continue;
st[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i]) {
int j=e[i];
if(dist[j]>(ll)dist[ver]+w[i]) {
dist[j]=dist[ver]+w[i];
q.push({dist[j],j});
}
}
}
}
int main() {
n=read(),m=read(),C=read();
memset(h,-1,sizeof h);
bool flag=false;
for(int i=1;i<=m;i++) {
int a,b,c;
a=read(),b=read(),c=read();
add(a,b,c);
if(C>=c) flag=true;
edge[i]={a,b,c};
}
for(int i=1;i<=n;i++) dijkstra(i,dist[i]);
ll ans=1e18;
for(int i=1;i<=m;i++) {
int a=edge[i].a,b=edge[i].b,c=edge[i].c;
ans=min(ans,(ll)c+dist[b][a]);
}
if(ans<=(ll)C) printf("2\n");
else if(flag) printf("1\n");
else printf("0\n");
return 0;
}