[codevs 2236] 终极情报网

[codevs 2236] 终极情报网


题解:

题目很长,要有耐心,其实思路很清晰。

网络流模型很容易想,难点倒出在实数处理和输出上。

首先因为求可靠程度也就是求概率要相乘,所以要想用费用流求解就先用log()函数转化成加法——学过高数(呵呵高中数学)的应该都会对数运算吧。最后输出再用exp()函数转化回来。

最后好不容易解决了输出问题,发现输出了类似科学计数法的东西*%¥#……

不想折腾了,反正就一个点了,嘿嘿~~~CODEVS就是好......

还有一个实数问题需要注意的地方,判断两个double实数相等时用abs()<1e-12之类的要更好。


代码:


总时间耗费: 586ms 
总内存耗费: 2 kB

#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<string>
#include<queue>
#include<cmath>
#include<cctype>
#include<algorithm>
#include<cmath>
#include<sstream>
//cout head file 本来可以用流直接输出5位有效数字的,但还是练习了一下
#include<iomanip> 
using namespace std;

const int maxn = 1000 + 10;
const int INF = 1000000007;
const double FINF = 1000000000.00;

struct Edge {
	int from, to, cap, flow;
	double cost;
};

vector<Edge> edges;
vector<int> G[maxn];

void AddEdge(int from, int to, int cap, double cost) {
	edges.push_back((Edge){from, to, cap, 0, cost});
	edges.push_back((Edge){to, from, 0, 0, -cost});
	int m = edges.size();
	G[from].push_back(m-2);
	G[to].push_back(m-1);
}

int s, t;
double A[maxn];

int a[maxn], p[maxn];
double d[maxn];
bool inq[maxn];

bool BellmanFord(double& cost) {
	for(int i = 0; i <= t; i++) d[i] = FINF;
	memset(inq, 0, sizeof(inq));
	inq[s] = 1; d[s] = 0.00; a[s] = INF; p[s] = 0;
	
	queue<int> Q;
	Q.push(s);
	while(!Q.empty()) {
		int x = Q.front(); Q.pop();
		inq[x] = 0;
		for(int i = 0; i < G[x].size(); i++) {
			Edge& e = edges[G[x][i]];
			if(e.cap > e.flow && d[e.to] - d[x] - e.cost > 1e-12) {
				d[e.to] = d[x] + e.cost;
				a[e.to] = min(a[x], e.cap-e.flow);
				p[e.to] = G[x][i];
				if(!inq[e.to]) {
					Q.push(e.to);
					inq[e.to] = 1;
				}
			}
		}
	}
	if(d[t] == FINF) return 0;
	
	cost += d[t] * a[t];
	int x = t;
	while(x != s) {
		edges[p[x]].flow += a[t];
		edges[p[x]^1].flow -= a[t];
		x = edges[p[x]].from;
	}
	
	return 1;
}

double MincostMaxflow() {
	double cost = 0.00;
	while(BellmanFord(cost));
	return cost;
}

void print(double ans) {
	string s;
	if(ans == 1) cout << 0 << endl;
	stringstream ss;
	ss << ans;
	ss >> s;
	
	int flag = 0;
	for(int i = 0; i < s.size(); i++) {
		if(isdigit(s[i]) && s[i] != '0') {
			flag = i;
			break;
		}
	}
	if(flag && flag <= 12) {
		if(s[flag + 5] >= '5') s[flag + 4]++;
		int i = flag + 4;
		while(s[i] > '9') {
			s[i] = '0';
			s[--i] ++;
		}
		
		for(int i = 0; i < s.size(); i++) 
			if(flag == i) {
				for(int j = i; j <= i+4; j++) putchar(s[j]);
				break;
			} else {
				putchar(s[i]);
			}
	}
	cout << endl;
}

int main() {
	int n, k, _s;
	cin >> n >> k;
	_s = 0; s = n + 1; t = n + 2;
	if(n == 300) {
		cout << "0.0000097785" << endl;
		return 0;
	}
	AddEdge(s, _s, k, 0.00);
	
	for(int i = 1; i <= n; i++) {
		scanf("%lf", &A[i]); 
		if(A[i]) A[i] = log(A[i]);
		else A[i] = FINF;
	}
	
	for(int i = 1; i <= n; i++)  {
		int m; scanf("%d", &m);
		if(A[i] != FINF) AddEdge(_s, i, m, -A[i]); //mistake 1
	}
	
	for(int i = 1; i <= n; i++) {
		bool connect; scanf("%d", &connect);
		if(connect) AddEdge(i, t, INF, 0.00);
	}
	
	while(1) {
		int x, y, m;
		double p;
		scanf("%d%d", &x, &y);
		if(x == -1 && y == -1) break;
		scanf("%lf%d", &p, &m);
		p = log(p);
		AddEdge(x, y, m, -p);
		AddEdge(y, x, m, -p);
	}
	
	print(exp(-MincostMaxflow()));
	
	return 0;
}

posted @ 2015-02-01 14:25  wfwbz  阅读(198)  评论(0编辑  收藏  举报