【网络流】【BZOJ1070】【SCOI2007】修车

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1070

题意:问你如何分配老司机使得每部车的等待时间之和最短。

解题思路:本题不易正做,考虑逆向解答,显然我们有对于一部车,我们枚举它被第i个老司机倒数第j个修,这样的带来的等待时间便是一定的。因此我们考虑枚举建点,建第j个老司机倒数第k个修第i部车,这样的话我们可以比较轻松的就可以建出一个网络,然后跑一遍最小费用最大流即可。

AC代码(用的比较low的SPFA费用流,但是在优化常数后就比学长写的P-D慢了一点)

#include<stdio.h>
#include<string.h>
#define inf 0x7fffffff
#define min(a,b) (a<b?a:b)
#define S 0
#define T 1001
#define length 2005
struct zxy{int to,next,c,v;}edge[200100];
int n,m,cnt=1,head[1005],dist[1005],que[2005],pre[1005];
bool vis[1005];
inline int in(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void ins(int x,int y,int v,int l){
    edge[++cnt].to=y,edge[cnt].next=head[x],edge[cnt].v=v,edge[cnt].c=l,head[x]=cnt;
    edge[++cnt].to=x,edge[cnt].next=head[y],edge[cnt].v=0,edge[cnt].c=l*(-1),head[y]=cnt;
}
bool SPFA_costflow(int s,int e){
    memset(dist,127/3,sizeof(dist));
    register int h=0,t=1,w,v;
    que[1]=s; vis[s]=1; dist[s]=0;
    while(h!=t){
        (++h)%=length;
        w=que[h];
        for (register int i=head[w]; i; i=edge[i].next)
            if (dist[edge[i].to]>dist[w]+edge[i].c&&edge[i].v){
                v=edge[i].to; pre[v]=i;
                dist[v]=dist[w]+edge[i].c;
                if (!vis[v]){
                    vis[v]=1;
                    if (dist[v]<dist[h+1]){          
                        que[h]=v;
                        h=(h-1+length)%length;
                    }
                    else{
                        (++t)%=length;
                        que[t]=v;
                    }
                }
            }
        vis[w]=0;
    }
    return dist[e]!=dist[T+1];
}
int cost_flow(int s,int t){
    int cost=0;
    while(SPFA_costflow(s,t)){
        int mi=inf;
        for (register int i=t; i; i=edge[pre[i]^1].to)
            mi=min(mi,edge[pre[i]].v);
        for (register int i=t; i; i=edge[pre[i]^1].to)
            edge[pre[i]].v-=mi,edge[pre[i]^1].v+=mi;
        cost+=dist[t]*mi;
    }
    return cost;
}
void init(){
    m=in(),n=in();
    for (int i=1; i<=n; ++i){
        for (int j=1; j<=m; ++j){
            int l=in();
            for (int k=1; k<=n; ++k)
                ins(i,j*n+k,1,k*l);
            ins(j*n+i,T,1,0);
        }
        ins(S,i,1,0);
    }
}
int main(){
    init();
    printf("%.2lf",1.0*cost_flow(S,T)/n);
}

 

posted @ 2017-03-22 09:46  Melacau  阅读(204)  评论(0编辑  收藏  举报