bzoj1070 [SCOI2007]修车 费用流+拆分

这个题一开始容易想到最暴力的建法,由于前面的决策影响后面的人的等待时间,所以就枚举第几个选第几辆,

由于有后面受前面影响,所以也可以看成前面对后面影响,影响的最多n个,所以就枚举影响建图,由于3辆车 安排4个一定不如3个优,就没有后效性了


码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int tot=-1,hou[2000007],hf[10][99],che[99],s,t,qj[2000007],xia[2000007],zhong[2000007],c[2000007],v[2000007],cnt,n,m,i,j,k,ans,d[2000007];
bool vis[2000007];
#define inf 9999999
queue<int>q;
void jian(int a,int b,int C,int d)
{
    ++tot;hou[tot]=xia[a],xia[a]=tot;zhong[tot]=b;c[tot]=d,v[tot]=C;    
}
void jia(int a,int b,int c,int d)
{
    jian(a,b,c,d);
    jian(b,a,0,-d);
}
bool bfs()
{
    qj[s]=-1;
    int i;
    for(i=1;i<=cnt;i++)
    d[i]=inf;
    d[s]=0;q.push(s);
    while(!q.empty())
    {
        int st=q.front();
        q.pop();
        vis[st]=0;
        for(i=xia[st];i!=-1;i=hou[i])
        {
            if(v[i]==0)continue;
            int nd=zhong[i];
          if(d[nd]>d[st]+c[i])
          {qj[nd]=i^1;
            d[nd]=d[st]+c[i];
            if(vis[nd]==0)
            {
            vis[nd]=1;
              q.push(nd);   
            }
          }     
        }
    }
    if(d[t]==inf)return 0;
    int o=qj[t];
    while(o!=-1)
    {
        v[o]++;
        v[o^1]--;
        ans+=c[o^1];
        o=qj[zhong[o]];
    }
    return 1;
}
int mcmf()
{
while(bfs());
return ans; 
}
int main()
{
    memset(xia,-1,sizeof(xia));
    scanf("%d%d",&m,&n);
    for(i=1;i<=n;i++)
    for(j=1;j<=m;j++)
    scanf("%d",&hf[j][i]);
    cnt=m;
    for(i=1;i<=m;i++)//枚举人 
    {   
    for(j=1;j<=n;j++)//枚举第几个 
    {
        int o=++cnt;
jia(i,o,1,0);
    for(k=1;k<=n;k++)//枚举是第几辆
    {
        if(che[k]==0)che[k]=++cnt;
        jia(o,che[k],1,hf[i][k]*j); 
    }
    }
    }
    s=++cnt;t=++cnt;
    for(i=1;i<=m;i++)jia(s,i,inf,0);
    for(i=1;i<=n;i++)jia(che[i],t,1,0);
    printf("%.2lf",1.00*mcmf()/n);
}


猜你喜欢

转载自blog.csdn.net/haobang866/article/details/79284504
今日推荐