HNOI2009 最小圈
阿新 • • 發佈:2019-04-06
++ 二分答案 分數 bool 答案 ref can rom href
傳送門
省選之前再水一發
當做01分數規劃+spfa判負環的板子題。二分答案mid,之後每條邊邊權-mid,在上邊判是否有負環即可。
這裏沒有使用入隊n次的spfa判負環,用的是基於dfs的SPFA……我也不知道哪個更好其實……
#include<bits/stdc++.h> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') #define pr pair<int,int> #define mp make_pair #define fi first #define sc second using namespace std; typedef long long ll; const int M = 10005; const int N = 2000005; const int INF = 0x3f3f3f3f; const double eps = 1e-10; int read() { int ans = 0,op = 1;char ch = getchar(); while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();} while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar(); return ans * op; } struct edge { int next,to,from; double v,c; }e[M<<3]; int head[M],ecnt,n,m,x,y; bool vis[M],flag; double ans,z,dis[M]; void add(int x,int y,double z) { e[++ecnt] = {head[x],y,x,z}; head[x] = ecnt; } void spfa(int x,double cur) { vis[x] = 1; for(int i = head[x];i;i = e[i].next) { double d = e[i].v - cur; if(dis[e[i].to] > dis[x] + d) { if(vis[e[i].to] || flag) {flag = 1;break;} dis[e[i].to] = dis[x] + d,spfa(e[i].to,cur); } } vis[x] = 0; } int main() { n = read(),m = read(); rep(i,1,m) x = read(),y = read(),scanf("%lf",&z),add(x,y,z); double L = -1e6,R = 1e6; while(R - L > eps) { double mid = (L+R) / 2.0; memset(dis,0,sizeof(dis)),memset(vis,0,sizeof(vis)),flag = 0; rep(i,1,n) { spfa(i,mid); if(flag) break; } if(flag) R = mid; else L = mid; } printf("%.8lf\n",L); return 0; }
HNOI2009 最小圈