列表

详情


NC50384. 最小圈

描述

考虑带权的有向图G=(V,E)以及,每条边的权值定义为,令n=|V|。是G中的一个圈当且仅当(c_k,c_1)都在E中,这时称k为圈c的长度。同时令,并定义圈的平均值为:

即c上所有边的权值的平均值。
为G中所有圈c的平均值的最小值。现在的目标是:在给定了一个图G=(V,E)以及之后,请求出G中所有圈c的平均值的最小值

输入描述

第一行包含两个正整数n和m,并用一个空格隔开,其中n=|V|,m=|E|,分别表示图中有n个顶点和m条边;
接下来m行,每行包含用空格隔开的三个数,表示有一条边(i,j)且该边的权值为
输入数据保证图G=(V,E)连通,存在圈且有一个点能到达其他所有点。

输出描述

仅包含一个实数,要求输出到小数点后8位。

示例1

输入:

4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3

输出:

3.66666667

示例2

输入:

2 2
1 2 -2.9
2 1 -3.1

输出:

-3.00000000

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 142ms, 内存消耗: 888K, 提交时间: 2020-01-01 20:20:51

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 3e3+1;

struct Edge {
  int v;
  double w;
};
vector<Edge> G[MAXN];
int n, m;

bool inq[MAXN];
double dis[MAXN];

bool dfs(int s, double limit) {
  inq[s] = true;
  for (auto e: G[s]) {
    // double w = limit - e.w;
    double w = e.w - limit;
    if (dis[e.v] <= dis[s] + w) continue;
    if (inq[e.v]) return true;
    dis[e.v] = dis[s] + w;
    if (dfs(e.v, limit)) return true;
  }
  inq[s] = false;
  return false;
}

bool isValid(double limit) {
  for (int i = 1; i <= n; i++) {
    memset(dis, 0, sizeof(dis));
    memset(inq, 0, sizeof(inq));
    if (dfs(i, limit)) return true;
  }
  return false;
}

int main() {
  cin >> n >> m;
  while (m--) {
    int i, j; double w; cin >> i >> j >> w;
    G[i].push_back(Edge{j, w});
  }

  double lo = -1e7, hi = 1e7+1;
  while (hi - lo > 1e-9) {
    double mid = (lo + hi) / 2;
    if (!isValid(mid)) lo = mid;
    else hi = mid;
  }
  cout << fixed << setprecision(8) << lo << endl;
}

C++11(clang++ 3.9) 解法, 执行用时: 88ms, 内存消耗: 876K, 提交时间: 2020-05-28 10:14:53

#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e3+1;
struct Edge
{
	int v;
	double w;
};
vector<Edge> G[MAXN];
int n,m;
bool inq[MAXN];
double dis[MAXN];
bool dfs(int s,double limit)
{
	inq[s]=true;
	for(auto e:G[s])
	{
		double w=e.w-limit;
		if(dis[e.v]<=dis[s]+w) continue;
		if(inq[e.v]) return true;
		dis[e.v]=dis[s]+w;
		if(dfs(e.v,limit)) return true;
	}
	inq[s]=false;
	return false;
}
bool isValid(double limit)
{
	for(int i=1;i<=n;i++)
	{
		memset(dis,0,sizeof(dis));
		memset(inq,0,sizeof(inq));
		if(dfs(i,limit)) return true; 
	}
	return false;
}
int main()
{
	cin>>n>>m;
	while(m--)
	{
		int i,j;
		double w;
		cin>>i>>j>>w;
		G[i].push_back(Edge{j,w}); 
	}
	double lo=-1e7,hi=1e7+1;
	while(hi-lo>1e-9)
	{
		double mid=(lo+hi)/2;
		if(!isValid(mid)) lo=mid;
		else hi=mid;
	}
	cout<<fixed<<setprecision(8)<<lo<<endl;
}

上一题