【BZOJ】【P2542】【CTSC2001】【终极情报网】【费用流】【题解】

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2542

我只能说浮点运算太坑了……,记住有关浮点类的等式不等式都要手动比较!!,还有保留有效数字更坑,TMD C/C++为什么不自带?!?手写挂了好几次,从别人那里借鉴了一下

/*
	ID:zky
	OJ:BZOJ
	Index:1834
	Language:C++
*/
#include<cmath>
#include<iomanip>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
#define clear(x) memset(x,0,sizeof(x))
#define inf(x) memset(x,0x7f,sizeof(x))
#define Size G[u].size()
#define read3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define read4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
using namespace std;
int ss,s,t;
int n,m,k;
const int INF=INT_MAX;
const double eps=1e-6;
struct edge{
	int u,v,cap,flow;
	double cost;
};
vector<edge>edges;
vector<vector<int> >G;
double d[10001];
int cur[10001];
int vis[10001];
int prev[10001];
void add(int u,int v,int cap,double cost){
	edges.push_back((edge){u,v,cap,0,cost});
	G[u].push_back(edges.size()-1);
	edges.push_back((edge){v,u,0,0,-cost});
	G[v].push_back(edges.size()-1);
}
int a[10001];
bool spfa(int  &flow,double &cost){
	queue<int>q;
	q.push(s);
	for(int i=0;i<=1010;i++){
		vis[i]=0;
		d[i]=-999999999;
	}
	double B=d[0];
	d[s]=0;
	vis[s]=1;
	a[s]=INF;
	while(!q.empty()){
		int u=q.front();q.pop();vis[u]=0;
		for(int i=0;i<G[u].size();i++){
			edge &e=edges[G[u][i]];
			if(e.cap-e.flow>0&&d[e.v]<d[u]+e.cost&&fabs(d[e.v]-d[u]-e.cost)>1e-10){
				d[e.v]=d[u]+e.cost;
				prev[e.v]=G[u][i];
				a[e.v]=min(a[u],e.cap-e.flow);
				if(!vis[e.v]){
					vis[e.v]=1;
					q.push(e.v);
				}
			}
		}
	}
	if(fabs(d[t]-B)<=eps)return false;
	int u=t;
	flow+=a[t];
	cost+=a[t]*d[t]+1e-12;
	while(u!=s){
		edges[prev[u]].flow+=a[t];
		edges[prev[u]^1].flow-=a[t];
		u=edges[prev[u]].u;
	}
	return true;
}
int flow=0;
double cost=0;
void costflow(){
	while(spfa(flow,cost));
}
double AS[3110];
int AM[3110];
double res;
void deal(){
    char ch[40];
    double ans=res;
    sprintf(ch,"%.15lf\n",ans);
    int sum=0,i;
    for(i=0; sum<5; i++)
    {
        if((ch[i]!='0'&&ch[i]!='.')|sum>0)
            sum++;
    }
    if(ch[i]>='5')
        ch[i-1]++;
    ch[i]=0;
    for(; i>=0; i--)
    {
        if(ch[i]=='.')break;
        else if(ch[i]>'9') {
            ch[i-1]++,ch[i]='0';
        }
    }
    printf("%s\n",ch);
}
int main(){
	cin>>n>>k;
	G.resize(1010);
	ss=0;t=n+1;s=t+1;
	add(s,ss,k,log(1));
	for(int i=1;i<=n;i++){
		cin>>AS[i];
		AS[i]=log(AS[i]);
	}
	for(int i=1;i<=n;i++){
		cin>>AM[i];
	}
	for(int i=1;i<=n;i++){
		if(AM[i]>0)
		add(ss,i,AM[i],AS[i]);
	}
	int x;
	for(int i=1;i<=n;i++){
		cin>>x;
		if(x)add(i,t,k,log(1));
	}
	double y;
	int u,v;
	while(cin>>u>>v){
		if(u==-1&&v==-1)break;
		cin>>y>>x;y=log(y);
		add(u,v,x,y);
		add(v,u,x,y);
	}
	int deb=0;
	if(deb){
		for(int i=0;i<edges.size();i++){
			cout<<"#"<<i<<" ";
			cout<<edges[i].u<<" ->";
			cout<<edges[i].v<<"  ";
			cout<<"cap:"<<edges[i].cap<<"  ";
			cout<<"cost:"<<edges[i].cost<<endl;
		}
		
	}
	costflow();
	if(k!=flow){
		printf("%5f\n",0);
		return 0;
	}
	res=pow(M_E,cost);
	deal();
	return 0;
}


你可能感兴趣的:(网络流,bzoj)