二分答案+dfs判负圈。将边值减去m,如果存在负圈则有更小的环存在。注意边界。不用spfa的原因是这不是单源最短路?。。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define REP(i,s,t) for(int i=s;i<=t;i++) #define op() clr(head,0);pt=edges; #define qwq(x) for(edge *o=head[x];o;o=o->next) int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)) { if(c=='-') f=false;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=3005; const int maxn=10005; const double inf=0x7f7f7f7f; const double eps=1e-9; struct edge{ int to;double dist;edge *next; }; edge edges[maxn],*pt,*head[nmax]; int vis[nmax],n,m;double d[nmax]; void add(int u,int v,double d){ pt->to=v;pt->dist=d;pt->next=head[u];head[u]=pt++; } void init(){ op(); n=read(),m=read(); rep(i,m) { int u=read(),v=read();double d;scanf("%lf",&d); add(u,v,d); } } bool dfs(int x){ vis[x]=true; qwq(x) if(d[o->to]>d[x]+o->dist){ if(!vis[o->to]) { d[o->to]=d[x]+o->dist; if(dfs(o->to)) return true; } else return true; } vis[x]=false; return false; } bool check(double x){ rep(i,n) qwq(i) o->dist-=x; clr(vis,0);clr(d,0); rep(i,n) if(dfs(i)) return true; return false; } void work(){ double l=-1e7,r=1e7; //double l=-inf,r=inf; while(r-l>eps){ double mid=(l+r)/2; if(check(mid)) r=mid; else l=mid; rep(i,n) qwq(i) o->dist+=mid; } printf("%.8lf ",l); } int main(){ init();work();return 0; }
1486: [HNOI2009]最小圈
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 2012 Solved: 938
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
Sample Output
3.66666667