[SCOI 2007] 修车

[题目链接]

https://www.lydsy.com/JudgeOnline/problem.php?id=1070

[算法]

首先 , 我们发现 , 在倒数第i个修车会对答案产生i * k的贡献

将每辆车建一个点 , 每名技术人员建n个点 ,将车与技术人员连边 , 第i个技术人员的第j个点与第k辆车连边表示k是i修的倒数第j辆车

然后在这张图上求最小费用最大流 , 即可

时间复杂度 : O(Costflow(NM , N ^ 2M))

[代码]

#include<bits/stdc++.h>
using namespace std;
#define MAXN 550
const int INF = 1e9;

struct edge
{
        int to , w , cost , nxt;
} e[MAXN * MAXN * 2];

int n , m , tot , ans , S , T;
int a[MAXN][MAXN];
int head[MAXN * MAXN] , dist[MAXN * MAXN] , pre[MAXN * MAXN] , incf[MAXN * MAXN];
bool inq[MAXN * MAXN];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - ‘0‘;
    x *= f;
}
inline void addedge(int u , int v , int w , int cost)
{
        ++tot;
        e[tot] = (edge){v , w , cost , head[u]};
        head[u] = tot;
        ++tot;
        e[tot] = (edge){u , 0 , -cost , head[v]};
        head[v] = tot;
}
inline bool spfa()
{
        int l , r;
        static int q[MAXN * MAXN];
        for (int i = 1; i <= T; i++)
        {
                pre[i] = 0;
                dist[i] = INF;
                incf[i] = INF;
                inq[i] = false;
        }
        q[l = r = 1] = S;
        dist[S] = 0;
        inq[S] = true;
        while (l <= r)
        {
                int cur = q[l++];
                inq[cur] = false;
                for (int i = head[cur]; i; i = e[i].nxt)
                {
                        int v = e[i].to , w = e[i].w , cost = e[i].cost;
                        if (w > 0 && dist[cur] + cost < dist[v])
                        {
                                dist[v] = dist[cur] + cost;
                                incf[v] = min(incf[cur] , w);
                                pre[v] = i;
                                if (!inq[v])
                                {
                                        q[++r] = v;
                                        inq[v] = true;
                                }
                        }
                }
        }
        if (dist[T] != INF) return true;
        else return false;
}
inline void update()
{
        int now = T , pos;
        while (now != S)
        {
                pos = pre[now];
                e[pos].w -= incf[T];
                e[pos ^ 1].w += incf[T];
                now = e[pos ^ 1].to;
        }
        ans += dist[T] * incf[T];
}

int main()
{

        read(m); read(n);
        for (int i = 1; i <= n; i++)
        {
                for (int j = 1; j <= m; j++)
                {
                        read(a[i][j]);
                }
        }
        tot = 1;
        S = n * m + n + 1 , T = S + 1;
        for (int i = 1; i <= n; i++) addedge(S , i , 1 , 0);
        for (int i = 1; i <= n; i++)
        {
                for (int j = 1; j <= m; j++)
                {
                        for (int k = 1; k <= n; k++)
                        {
                                addedge(i , n + (j - 1) * n + k , 1 , a[i][j] * k);
                        }
                }
        }
        for (int i = 1; i <= n * m; i++) addedge(i + n , T , 1 , 0);
        while (spfa()) update();
        printf("%.2lf\n" , 1.0 * ans / n);

        return 0;

}

原文地址:https://www.cnblogs.com/evenbao/p/9863771.html

时间: 2024-10-10 20:10:29

[SCOI 2007] 修车的相关文章

BZOJ SCOI 2007 修车 费用流

题目大意:有一些车和一些修车的人,给出每个人修每个车的时间,问所有人等待的最短平均时间是多少. 思路:记得POJ有一个和这个很像的题,做法是一样的.对于每个人修车的时候,我们只考虑他修车的时间对在它之后修车的人的时间的影响,因此我们只要考虑每一辆车是倒数第几个修的就可以了,然后朴素的建图,跑朴素的费用流,就可以过. CODE: #include <queue> #include <cstdio> #include <cstring> #include <ioman

图论(网络流):SCOI 2007 修车

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

[BZOJ 1072][SCOI 2007]排列perm

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1072 这题范围小,s的长度不超过10,如果用二进制表示每一位数字是否被选择到的话,二进制最大不超过2^10,可以用状压DP做. 我们把这题分两步走 第一步,把输入的字符串s中所有的数字都当成不同的,在这种情况下求出方案总数 用f[S][j]表示当前每一位数字是否选到的二进制状态为S,拼出的数mod d=j的方案数. 决策就是可以从所有没有被选到的数字中,选择一个数放到之前拼好的数

BZOJ 1069 SCOI 2007 最大土地面积 凸包+旋转卡壳

题目大意:给出平面上的一些点,求其中四个点的最大四边形的面积. 思路:简单yy一下发现这些点肯定都在凸包上,先求个凸包.然后直接暴力肯定是不行的,我们需要一个O(n^2)的做法,比较简单的想法是枚举最后要求的四边形的一条对线,那么这个四边形就被分割成了两个三角形,剩下两个点与这条线组成的三角形的面积和就是答案. 按照旋转卡壳的思想不难发现,这两个点都是单调的.所以枚举对角线然后扫n圈就可以了. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cm

BZOJ 1066 SCOI 2007 蜥蜴 最大流

题目大意:给出一张图,每一个点有一个寿命,当有这个寿命值个蜥蜴经过后这个点就会消失,一个蜥蜴可以跳到距离不超过d的点上,问最少有多少只蜥蜴无法跳出这张图. 思路:我们将每个点拆点,然后限制流量为这个点的寿命,之后源点向每个蜥蜴连边,互相能够到达的点之间连边,能够跳出这个图的点和汇点连边,跑最大流就是这个图中最多能够跑出去的蜥蜴数量,最后在用总数减去就是最少不能逃出去的数量. CODE: #include <cmath> #include <queue> #include <c

[SCOI 2007] 排列

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1072 [算法] 状压DP [代码] #include<bits/stdc++.h> using namespace std; #define MAXD 1000 const int MAXS = 2048; int i,j,k,T,len,d,MASK; char s[20]; long long f[MAXS][MAXD]; long long ans; long long f

解题:SCOI 2007 蜥蜴

题面 拆点跑最大流 所有能跑出去的点连向汇点,容量为inf 原点连向所有初始有蜥蜴的点,容量为1 每根柱子拆成两个点"入口"和"出口",入口向出口连容量为高度的边,出口向别的有高度的柱子的入口连容量为高度的边 1 #include<cmath> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 co

[省选]省选知识点进度

联赛之后记录一下自己的知识点学习情况(按开始时间先后顺序) 可持久化数据结构 [BZOJ 3123]森林 树上主席树 启发式合并 LCA [BZOJ 4826]影魔 区间修改主席树 标记永久化 [BZOJ 2735]世博会 主席树 切比雪夫距离转曼哈顿距离 [BZOJ 3166]Alo 可持久化01Trie [BZOJ 3689]异或之 可持久化01Trie [BZOJ 3261]最大异或和 可持久化01Trie 树套树 [COGS 257]动态排名系统 树状数组套主席树 [BZOJ 2141]

Up to 8% free bonus for runescape 2007 gp on Rsorder as july best gift&Enjoy Telos During 7.1-7.22

Now, a small band of freedom fighters struggle to end the osrs gold  long, dark night of Daein's oppression. The big blog news of the day is that Vox Media has acquired Curbed Network. As an amulet you should be wearing an amulet of glory and if you