BZOJ1070

费用流。

源点连到n辆车,容量为1,费用为0

把每个工人拆成n个点,对于第j个工人第p个点,表示该工人 倒数 第p个完成该任务的代价,因为你现在做的任务不会影响到你的前几个任务,只会给后面添加代价,所以n辆车连到这些点,容量为1,代价为map[i][j]*p

这些点再连到汇点,容量为1,代价为0

最后注意下数组一定要足够大

#include<cstdio>
#include<cstdlib>
#include<cstring>
#define min(u1,u2) (u1<u2?u1:u2)
int map[1000][1000];
struct mod{int x,y,c,d,next,other;};
mod q[100000];
int first[10005];
int s[10000];
int t[10000];
bool vis[10000];
int pre[10000],pi[10000];
int maxx=1000000000;
int len=0,ans=0;
int S,T;
void ins(int x,int y,int c,int d)
{
len++;
q[len].x=x;
q[len].y=y;
q[len].c=c;
q[len].d=d;
q[len].next=first[x];
first[x]=len;
q[len].other=len+1;

len++;
q[len].x=y;
q[len].y=x;
q[len].c=0;
q[len].d=-d;
q[len].next=first[y];
first[y]=len;
q[len].other=len-1;
}
bool spfa()
{
memset(s,63,sizeof(s));
s[S]=0;
memset(vis,false,sizeof(vis));
vis[S]=true;
t[1]=S;
int st=1,ed=2;
while(st!=ed)
{
int x=t[st];
for (int i=first[x];i!=-1;i=q[i].next)
{
int y=q[i].y;
if (q[i].c>0&&s[x]+q[i].d<s[y])
{
s[y]=s[x]+q[i].d;
pre[y]=x;
pi[y]=i;
if (vis[y]==false)
{
vis[y]=true;
t[ed]=y;
ed++;
if (ed>T)ed=1;
}
}
}
vis[x]=false;
st++;
if (st>T)st=1;
}
if (s[T]>10000000)return false;
return true;
}
int fond()
{
ans=0;
while(spfa())
{
//for (int i=1;i<=len;i++)
//printf("i:%d x:%d y:%d c:%d d:%d\n",i,q[i].x,q[i].y,q[i].c,q[i].d);
//system("pause");
int minn=100000000;
for (int i=T;i!=S;i=pre[i])
minn=min(minn,q[pi[i]].c);
int o=minn*s[T];
ans+=o;
//printf("s:%d\n",s[T]);
for (int i=T;i!=S;i=pre[i])
{
q[pi[i]].c-=minn;
q[q[pi[i]].other].c+=minn;
}
}
return ans;
}
int main()
{
int n,m;
memset(first,-1,sizeof(first));
scanf("%d%d",&m,&n);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
}
S=0;
T=n+n*m+1;
for (int i=1;i<=n;i++)
ins(S,i,1,0);
for (int i=n+1;i<T;i++)
ins(i,T,1,0);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int k=1;k<=n;k++)
{
ins(i,j*n+k,1,(n-k+1)*map[i][j]);
}
double nn=(double)fond();
printf("%.2lf\n",nn/n);
}

时间: 2024-10-22 15:23:37

BZOJ1070的相关文章

bzoj1070 修车&amp;&amp; bzoj2879美食节 【费用流】

bzoj1070: 把每个工人拆成汽车那么多个点,假如说 工人(i, j) 和 汽车k 连边,那就代表第i个工人倒数第j个修汽车k,那么这条边对以后的贡献就是k*time[i修k]. 1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define drep(i, a, b) for (int i = a; i >= b; i--) 4 #define REP(i, a,

[bzoj1070][SCOI2007]修车_费用流

修车 bzoj-1070 SCOI-2007 题目大意:有m个人要修n台车,每个工人修不同的车的时间不同,问将所有的车都修完,最少需要花费的时间. 注释:$2\le m\le 9$,$1\le n \le 60$ 想法:想起了那句话...(如果题面复杂,dp状态不可描述,一看数据范围发现才几百,那八成是网络流了),一般这句话都是对的,除了那次在CF上遇到的爆搜.. ... 关于这道题,网上有题解在边上做技巧(完全没明白这样的意义),我的做法时拆点.将每个点拆成n个,然后在这些被拆的点与车之间连边

Bzoj1070 [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 5325  Solved: 2217 Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每

BZOJ1070 修车-费用网络流

http://www.lydsy.com/JudgeOnline/problem.php?id=1070 Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j

bzoj1070————2016——3——14

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1070: 题目概括: Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m

[BZOJ1070][SCOI2007]修车(最小费用最大流)

题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1070 分析: 把每个工人拆成N个点.记为A[i,j]表示第i个工人修倒数第j辆车. 每个车跟所有N*M个工人拆出的点连边.流量为1,费用为time[i,j]*k. 源和每辆车连边,N*M个点和汇连边,流量都为1,费用同为0. 为什么这么建呢?因为如果某个工人修了某辆车,那么只会对这个工人以后修的车的时间有影响,对已经修完的没影响,于是可以倒过来考虑.

[bzoj1070][SCOI2007]修车[ 网络流]

把每个工人拆成N个点.记为A[i,j]表示第i个工人修倒数第j辆车.每个车跟所有N*M个工人拆出的点连边.流量为1,费用为$time[i,j]*k$.源和每辆车连边,N*M个点和汇连边,流量都为1,费用同为0. 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include &

bzoj1070题解

[解题思路] 考虑拆点,得到一个二分图:左边点<i,j>表示第i个技师按顺序第j辆修的车,右边点k表示第k个车主,连接左右的边表示第k个车主可能成为第i个技师的第j个客户. 虽然是二分图,但直接跑匈牙利会跪,于是考虑费用流,左图都和源点连边,右图都和汇点连边,跑个流即可.复杂度O(松). [参考代码] 1 #pragma GCC optimize(2) 2 #include <cstdio> 3 #include <cstring> 4 #define REP(i,lo

[BZOJ1070] [SCOI2007] 修车 (费用流 &amp; 动态加边)

Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. Input 第一行有两个m,n,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. Output 最小平均等待时间,答案精确到小数点后2位