zoukankan      html  css  js  c++  java
  • [SCOI2007]修车 BZOJ1070

    很久之前写的题了,今天翻出来写一篇博客复习一下...

    分析:

    考虑,T <= 1000,并不能针对这一维处理,所以考虑将,每个人拆点,之后,拆完之后表示,这个人第n-j+1个修k这辆车,也就是,m*(i-1)+j向n*m+k连边,流量为1,费用为t[i][k]*j,之后建图跑费用流。

    BZOJ上我之前跑过去了,但是现在改时间限制了...现在跑不过了...不过luogu上没有问题...

    附上代码:

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <cstring>
    using namespace std;
    #define N 2005
    #define S 0
    #define T 2004
    int head[N],cnt,n,m;
    struct node
    {
        int to,next,val,flow,from;
    }e[N*40];
    inline void add(int x,int y,int z,int v)
    {
        e[cnt].from=x;
        e[cnt].to=y;
        e[cnt].next=head[x];
        e[cnt].val=v;
        e[cnt].flow=z;
        head[x]=cnt++;
        e[cnt].from=y;
        e[cnt].to=x;
        e[cnt].next=head[y];
        e[cnt].val=-v;
        e[cnt].flow=0;
        head[y]=cnt++;
        return ;
    }
    int vis[N],dis[N],que[N];
    int fro[N];
    int spfa()
    {
        memset(fro,-1,sizeof(fro));
        memset(dis,0x3f,sizeof(dis));
        int l=0,r=0;
        que[r++]=S;
        vis[S]=1;
        dis[S]=0;
        while(l<r)
        {
            int x=que[l++];
            vis[x]=0;
            for(int i=head[x];i!=-1;i=e[i].next)
            {
                int to1=e[i].to;
                if(e[i].flow&&dis[to1]>dis[x]+e[i].val)
                {
                    dis[to1]=dis[x]+e[i].val;
                    fro[to1]=i;
                    if(!vis[to1])
                    {
                        que[r++]=to1;
                        vis[to1]=1;
                    }
                }
            }
        }
        if(dis[T]>(1<<25))
        {
            return 0;
        }
        return 1;
    }
    inline void update(int i,int c)
    {
        e[i].flow-=c;
        e[i^1].flow+=c;
        return ;
    }
    int ans;
    void mcf()
    {
        int i,x=1<<30;
        i=fro[T];
        while(i!=-1)
        {
            x=min(e[i].flow,x);
            i=fro[e[i].from];
        }
        i=fro[T];
        while(i!=-1)
        {
            e[i].flow-=x;
            e[i^1].flow+=x;
            ans+=x*e[i].val;
            i=fro[e[i].from];
        }
    }
    int t[105][105];
    int main()
    {
        for(int i=0;i<N;i++)
        {
            head[i]=-1;
        }
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&t[i][j]);
            }
        }
        for(int i=1;i<=n*m;i++)
        {
            add(0,i,1,0);
        }
        for(int i=n*m+1;i<=n*m+n;i++)
        {
            add(i,T,1,0);
        }
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                for(int k=1;k<=n;k++)
                {
                    add((i-1)*n+j,m*n+k,1,t[k][i]*j);
                }
            }  
        }
        while(spfa())
        {
            mcf();
        }
        printf("%.2lf
    ",(1.0*ans)/(1.0*n));
        return 0;
    }
    

      

  • 相关阅读:
    计算长度的方法
    自动装箱和拆箱
    基本数据包装类
    Date类
    文档参数解析
    权限修饰符
    IO流
    ArrayList集合类
    对象数组
    二维数组
  • 原文地址:https://www.cnblogs.com/Winniechen/p/9298466.html
Copyright © 2011-2022 走看看