bzoj1486: [HNOI2009]最小圈

二分答案+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 MB
Submit: 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

Sample Output

3.66666667

HINT

 

Source

 
[Submit][Status][Discuss]
原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5675231.html