BZOJ 1070 [SCOI2007]修车【费用流

80 篇文章 0 订阅
3 篇文章 0 订阅

建图看hzwer的blog吧QAQ讲得超好


第一次写zkw费用流……为了学这个专门去看了KM…………

WA了一年……

zkw倒是一遍写对了

然而

n,m写反,调了一年

……真的……不想承认……我费用流建边写错了……反向边……的费用……我……写的是……零………………

mdzz,看来要退役了


#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MAXN 700
#define MAXM 70000
using namespace std;	int n,m;
long long cost=0;
int S=0,T=657;
struct t1{
	int to,nxt,c,liu;
	t1(){}
	t1(int to,int nxt,int c,int liu):to(to),nxt(nxt),c(c),liu(liu){}
}edge[MAXM];	int cnt_edge=1;
int fst[MAXN],cnt_node=0;
void addedge(int x,int y,int c,int liu){
	edge[++cnt_edge]=t1(y,fst[x],c,liu);
	fst[x]=cnt_edge;
	edge[++cnt_edge]=t1(x,fst[y],-c,0);
	fst[y]=cnt_edge;
}

int vis[MAXN],ust=0;

int flow(int now,int low){
	if(now==T)	return cost+=ust*low,low;
	vis[now]=1;
	int rst=low;
	for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
		if((!edge[tmp].liu)||vis[edge[tmp].to]||edge[tmp].c)	continue;
		int aim=edge[tmp].to;
		int dd=flow(aim,min(rst,edge[tmp].liu));
		edge[tmp].liu-=dd,edge[tmp^1].liu+=dd,rst-=dd;
		if(!rst)	return low;
	}
	return low-rst;
}

bool check(){
	int d=INF;
	for(int i=S;i<=T;++i)
		if(vis[i])
			for(int tmp=fst[i];tmp;tmp=edge[tmp].nxt)
				if(edge[tmp].liu&&(!vis[edge[tmp].to])&&edge[tmp].c<d)
					d=edge[tmp].c;
	if(d==INF)	return 0;
	for(int i=S;i<=T;++i)
		if(vis[i])
			for(int tmp=fst[i];tmp;tmp=edge[tmp].nxt)
				edge[tmp].c-=d,edge[tmp^1].c+=d;
	return ust+=d,1;
}


void cost_flow(){
	do	
		do{
//			puts("QAQ");
			memset(vis,0,sizeof vis);
		} while(flow(S,INF));
	while(check());
}

int id_node[10][61];
int read_t;
int main(){
	scanf("%d%d",&m,&n);

	cnt_node=n;
	for(int i=1;i<=n;++i)	addedge(S,i,0,1);
	for(int i=1;i<=m;++i)
		for(int j=1;j<=n;++j)
			id_node[i][j]=++cnt_node,
			addedge(cnt_node,T,0,1);
			
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j){
			scanf("%d",&read_t);
			int ttmp=read_t*n;
			for(int k=1;k<=n;++k,ttmp-=read_t)
				addedge(i,id_node[j][k],ttmp,1);
		}

	cost_flow();
	printf("%.2f",1.0*cost/n);	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值