【一本通】最小圈
💐The Begin💐点点关注,收藏不迷路💐
|
对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值
输入
第一行2个正整数,分别为n和m
以下m行,每行3个数,表示边连接的信息,
输出
一行一个数,表示最小圈的值,保留8位小数。
样例输入
【样例输入1】
4 5
1 2 5
2 3 5
3 1 5
2 4 3
4 1 3
【样例输入2】
2 2
1 2 -2.9
2 1 -3.1
样例输出
【样例输出1】
3.66666667
【样例输出2】
-3.00000000
#include <iostream
>
#include <cstdio
>
#include <cstring
>
#include <algorithm
>
using namespace std;
typedef double Double; // 定义别名Double表示double类型
const int MAX_NODE_NUM = 3005; // 最大节点数量
const int MAX_EDGE_NUM = 10005; // 最大边数量
const Double PRECISION = 1e-10; // 精度限制
// 快速读取整数
inline void readInt(int &num) {
num = 0;
char ch = getchar();
while (ch < ‘0’ || ch > ‘9’) ch = getchar();
while (ch >= ‘0’ && ch <= ‘9’) {
num = (num << 1) + (num << 3) + (ch ^ 48);
ch = getchar();
}
}
int nodeNum; // 节点数量
int edgeNum; // 边数量
int edgeIndex; // 边的索引
int head[MAX_NODE_NUM]; // 邻接表头指针
Double dist[MAX_NODE_NUM]; // 最短距离
bool visited[MAX_NODE_NUM]; // 节点访问标记
struct Edge {
int nextEdgeIndex; // 下一条边的索引
int targetNode; // 目标节点
Double edgeWeight; // 边的权重
} edges[MAX_EDGE_NUM << 1]; // 边数组
// 插入边
inline void insertEdge(int fromNode, int toNode, int weight) {
edgeIndex++;
edges[edgeIndex].nextEdgeIndex = head[fromNode];
edges[edgeIndex].targetNode = toNode;
edges[edgeIndex].edgeWeight = (Double)weight;
head[fromNode] = edgeIndex;
}
// 判断是否存在负权环,通过调整limit参数判断
bool checkNegativeCycle(int startNode, Double limit) {
visited[startNode] = true;
for (int i = head[startNode]; i; i = edges[i].nextEdgeIndex) {
int target = edges[i].targetNode;
if (dist[target] > dist[startNode] + edges[i].edgeWeight - limit) {
if (visited[target]) return true;
else {
dist[target] = dist[startNode] + edges[i].edgeWeight - limit;
if (checkNegativeCycle(target, limit)) return true;
}
}
}
return visited[startNode] = false;
}
// 判断是否存在负权环,limit为判断阈值
inline bool hasNegativeCycle(Double limit) {
memset(visited, 0, sizeof(visited));
memset(dist, 0, sizeof(dist));
for (int i = 1; i <= nodeNum; ++i)
if (checkNegativeCycle(i, limit)) return true;
return false;
}
int main() {
readInt(nodeNum);
readInt(edgeNum);
for (int i = 1; i <= edgeNum; ++i) {
int from, to, weight;
readInt(from);
readInt(to);
readInt(weight);
insertEdge(from, to, weight);
}
Double left = 0.0;
Double right = 50000.0;
Double mid;
while (right - left > PRECISION) {
mid = (left + right) / 2.0;
if (hasNegativeCycle(mid)) right = mid;
else left = mid;
}
printf(“%.8lf”, right);
return 0;
}
💐The End💐点点关注,收藏不迷路💐
|