bzoj1070: [SCOI2007]修车

本来想写美食节的。。但是动态加点不会,今晚有点困,所以就写这题弱化版了。

然后做法就是把一个修理工拆成n个,表示倒数第几个修当前这辆车,这样做的原因就是修一部车的影响是对于后面的车的。

复习一波费用流。

 

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int m,n;

struct node
{
    int x,y,c,d,next,other;
}a[110000];int len,last[1100];
void ins(int x,int y,int c,int d)
{
    int k1,k2;
    
    len++;k1=len;
    a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d;
    a[len].next=last[x];last[x]=len;
    
    len++;k2=len;
    a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d;
    a[len].next=last[y];last[y]=len;
    
    a[k1].other=k2;
    a[k2].other=k1;
}

int st,ed;
int w[110][20];
void composition()
{
    for(int i=1;i<=n;i++)ins(st,i,1,0);
    for(int j=n+1;j<=n+m*n;j++)ins(j,ed,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,w[i][j]*(n-k+1));
}

//---------composition---------------

int ans;
int list[1100],d[1100];
bool v[1100];
int pre[1100],cc[1100];
bool spfa()
{
    memset(d,63,sizeof(d));
    memset(v,false,sizeof(v));
    list[1]=st;d[st]=0;v[st]=true;
    
    memset(cc,0,sizeof(cc));cc[st]=2147483647;
    
    int head=1,tail=2;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(d[y]>d[x]+a[k].d&&a[k].c>0)
            {
                d[y]=d[x]+a[k].d;
                pre[y]=k;
                cc[y]=min(a[k].c,cc[x]);
                if(v[y]==false)
                {
                    v[y]=true;
                    list[tail]=y;
                    tail++;if(tail==1050)tail=1;
                }
            }
        }
        v[x]=false;
        head++;if(head==1050)head=1;
    }
    
    if(d[ed]>=999999999)return false;
    else
    {
        ans+=d[ed]*cc[ed];
        int y=ed;
        while(st!=y)
        {
            int k=pre[y];
            a[k].c-=cc[ed];a[a[k].other].c+=cc[ed];
            y=a[k].x;
        }
        return true;
    }
}

//------------spfa-------------------

int main()
{
    scanf("%d%d",&m,&n);
    st=n+m*n+1,ed=n+m*n+2;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&w[i][j]);
    
    composition();
    
    ans=0;
    while(spfa()==true);
    printf("%.2lf\n",double(ans)/double(n));
    return 0;
}

 

posted @ 2018-01-23 21:49  AKCqhzdy  阅读(147)  评论(0编辑  收藏  举报