可耻的苟到数据后搞了一波题
首先标解绝对不是倍增floyd
这是n^3logn的算法
二分+DFS_SPFA是nlogn的算法
但是在学习嘛
所谓标解:
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int n,m;
struct Matrix{
int a[N][N];
friend Matrix operator * (Matrix A,Matrix B){
Matrix C;
memset(C.a,0x3f,sizeof(C.a));
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
C.a[i][j]=min(C.a[i][j],A.a[i][k]+B.a[k][j]);
}
}
}
return C;
}
}a[N],x;
int main(){
// cout<<"218"<<'\n';
scanf("%d%d",&n,&m);
// cout<<"8791897"<<'\n';
memset(x.a,0x3f,sizeof(x.a));
memset(a[0].a,0x3f,sizeof(a[0].a));
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
a[0].a[u][v]=w;
}
for(int i=1;i<=n;i++){
a[0].a[i][i]=x.a[i][i]=0;
}
int len=0;
while((1<<len)<=n)len++;
len--;
for(int i=1;i<=len;i++){
a[i]=a[i-1]*a[i-1];
}
Matrix tmp;
int ans=0;
for(int j=len;j>=0;j--){
tmp=x*a[j];
int flag=1;
for(int i=1;i<=n;i++){
if(tmp.a[i][i]<0){
flag=0;
break;
}
}
if(flag==1)
x=tmp,ans+=(1<<j);
}
if(ans>n)cout<<0;
cout<<ans+1;
}
比标解快几倍的解法:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
const int ONE = 305;
const int EDG = ONE*ONE;
int n,m;
int x,y,z;
int nxt[EDG],first[EDG],go[EDG],w[EDG],tot;
int vis[ONE],dist[ONE];
int PD;
int get()
{
int res=1,Q=1; char c;
while( (c=getchar())<48 || c>57)
if(c=='-')Q=-1;
if(Q) res=c-48;
while((c=getchar())>=48 && c<=57)
res=res*10+c-48;
return res*Q;
}
void Add(int u,int v,int z)
{
nxt[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z;
}
void Spfa(int u,int T,int Limit)
{
if(PD) return;
for(int e=first[u];e;e=nxt[e])
{
int v = go[e];
if(dist[u]+w[e] <= dist[v])
{
if(vis[v]) {PD = 1; return;}
if(T==Limit) return;
dist[v] = dist[u] + w[e];
vis[v] = 1;
Spfa(v,T+1,Limit);
vis[v] = 0;
}
}
}
int Check(int Limit)
{
PD = 0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis)); vis[i] = 1;
memset(dist,0,sizeof(dist));
Spfa(i,1,Limit);
if(PD) return 1;
}
return 0;
}
int main()
{
n=get(); m=get();
for(int i=1;i<=m;i++)
{
x=get(); y=get(); z=get();
Add(x,y,z);
}
if(!Check(n)) {printf("0"); exit(0);}
int l=1, r=n;
while(l < r-1)
{
int mid = l+r>>1;
if(Check(mid)) r = mid;
else l = mid;
}
if(Check(l)) printf("%d",l);
else printf("%d",r);
}