易知负环长度不超过n
考虑朴素做法,f[i][j][k]代表从i到j,最多k条边,最小长度
那么没转移一次看有没有负环即可
复杂度n^2m
但是并不知道题面里那个m的范围什么鬼
我们可以考虑倍增优化这个东西
就是倍增floyd那种
从大到小枚举2的幂,如果做2^i次转移后还没有负环就做2^i次转移,否则不做
类似倍增LCA
复杂度n^3logn
但是由于m玄学的范围跑的比暴力慢-_-
暴力:
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 310
#define MAXM 90010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
struct vec{
int to;
int fro;
int v;
};
vec mp[MAXM*2];
int tai[MAXN],cnt;
int n,m;
int f[MAXN][MAXN],g[MAXN][MAXN];
inline void be(int x,int y,int z){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
mp[cnt].v=z;
}
inline void bde(int x,int y,int z){
be(x,y,z);
be(y,x,z);
}
int main(){
int i,j,x,y,z;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
be(x,y,z);
}
memset(f,0x3f,sizeof(f));
for(i=1;i<=n;i++){
f[i][i]=0;
}
for(i=1;i<=n;i++){
memcpy(g,f,sizeof(g));
for(z=1;z<=n;z++){
for(x=1;x<=n;x++){
for(j=tai[x];j;j=mp[j].fro){
y=mp[j].to;
g[z][y]=min(g[z][y],f[z][x]+mp[j].v);
}
}
}
memcpy(f,g,sizeof(f));
for(x=1;x<=n;x++){
if(f[x][x]<0){
printf("%d\n",i);
return 0;
}
}
}
printf("0\n");
return 0;
}
/*
*/
倍增:
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 310
#define MAXM 90010
#define ll long long
#define eps 1e-8
#define MOD 1000000007
#define INF 1000000000
int n;
struct mat{
int x[MAXN][MAXN];
mat(){
memset(x,0x3f,sizeof(x));
}
friend mat operator *(mat x,mat y){
int i,j,k;
mat z;
for(k=1;k<=n;k++){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
z.x[i][j]=min(x.x[i][k]+y.x[k][j],z.x[i][j]);
}
}
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
z.x[i][j]=min(z.x[i][j],min(x.x[i][j],y.x[i][j]));
}
}
return z;
}
};
int m;
mat c[11];
int mi[11];
mat now;
int ans;
bool hs(mat x){
int i;
for(i=1;i<=n;i++){
if(x.x[i][i]<0){
return 1;
}
}
return 0;
}
int main(){
int i,j,x,y,z;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
c[1].x[x][y]=z;
}
for(i=1;i<=n;i++){
now.x[i][i]=0;
}
c[1]=now*c[1];
mi[1]=1;
for(i=2;i<=10;i++){
c[i]=c[i-1]*c[i-1];
mi[i]=mi[i-1]<<1;
}
for(i=10;i;i--){
mat t=now*c[i];
if(!hs(t)){
now=t;
ans+=mi[i];
}
}
if(hs(now*c[1])){
printf("%d\n",ans+1);
}else{
printf("0\n");
}
return 0;
}
/*
*/