码迷,mamicode.com
首页 > 其他好文 > 详细

[SCOI 2007] 修车

时间:2018-10-27 22:59:01      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:int   namespace   git   temp   pen   inline   mes   php   www   

[题目链接]

          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;
    
}

 

[SCOI 2007] 修车

标签:int   namespace   git   temp   pen   inline   mes   php   www   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!