• BZOJ1070[SCOI2007]修车


    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1070

    codevs上也有哦:http://codevs.cn/problem/2436/

    这题感觉还是比较好想的。

    因为算的是平均等待时间,那么就要考虑分配问题和顺序问题。

    首先我们从s向每个汽车连容量为1,费用为0的边。

    然后我们将师傅拆点,拆成n分,可以看做是倒数多少个的状态。

    那么我们将每个汽车(i)向每个状态(j,k)都连一条容量为1,费用为k*w[j][i]的边。

    表示师傅j在倒数第k个做i产生的贡献值。

    然后再将每个状态往t连容量为1,费用为0的边。

    跑最小费用最大流就可以了。

    这题,因为连边多一点,所以zkw稍慢一点点:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=65*65;
    const int INF=0x3f3f3f3f;
    
    struct Node{
        int data,next,low,cost;
    }node[maxn*9*2];
    
    #define www node[point].low
    #define now node[point].data
    #define ccc node[point].cost
    #define then node[point].next
    
    int n,m,cnt;
    int s,t,ans;
    int head[maxn],cur[maxn];
    int dis[maxn];
    int a[65][65];
    bool vis[maxn];
    
    void add(int u,int v,int w,int c){
        node[cnt].data=v;node[cnt].next=head[u];node[cnt].low=w;node[cnt].cost=c;head[u]=cnt++;
        node[cnt].data=u;node[cnt].next=head[v];node[cnt].low=0;node[cnt].cost=-c;head[v]=cnt++;
    }
    
    int dfs(int x,int low){
        if(x==t) return low;
        int Low;vis[x]=true;
        for(int &point=cur[x];point!=-1;point=then)
            if(www && !vis[now] && dis[x]==dis[now]+ccc){
                Low=dfs(now,min(low,www));
                if(Low){
                    www-=Low,node[point^1].low+=Low;
                    return Low;
                }
            }
        return 0;
    }
    
    bool modify(){
        int ad=INF;
        for(int i=s;i<=t;i++)
        if(vis[i])
            for(int point=head[i];point!=-1;point=then)
            if(www && !vis[now])
                ad=min(ad,dis[now]+ccc-dis[i]);
        if(ad==INF) return false;
        for(int i=s;i<=t;i++)
        if(vis[i])
            vis[i]=false,dis[i]+=ad;
        return true;
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("1070.in","r",stdin);
        freopen("1070.out","w",stdout);
    #endif
    
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
        t=n*(m+1)+1;
        for(int i=s;i<=t;i++) head[i]=-1;
        for(int i=1;i<=n;i++) add(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++)
                    add(i,j*n+k,1,k*a[i][j]);
        for(int i=n+1;i<t;i++) add(i,t,1,0);
        
        int flag;
        do{
            for(int i=s;i<=t;i++) cur[i]=head[i];
            while(flag=dfs(s,INF))
                ans+=flag*dis[s];
        }while(modify());
        printf("%.2lf",(double)ans/n);
        return 0;
    }
    View Code

    spfa似乎快了那么40ms?never mind,反正只是当练习模板了。

    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=65*65;
    const int INF=0x3f3f3f3f;
    
    struct Node{
        int data,next,low,cost;
    }node[maxn*9*2];
    
    #define www node[point].low
    #define now node[point].data
    #define ccc node[point].cost
    #define then node[point].next
    
    int n,m,cnt;
    int s,t,ans;
    int head[maxn],cur[maxn];
    int dis[maxn],pre[maxn];
    int a[65][65];
    bool inq[maxn];
    deque<int >q;
    
    void add(int u,int v,int w,int c){
        node[cnt].data=v;node[cnt].next=head[u];node[cnt].low=w;node[cnt].cost=c;head[u]=cnt++;
        node[cnt].data=u;node[cnt].next=head[v];node[cnt].low=0;node[cnt].cost=-c;head[v]=cnt++;
    }
    
    bool SPFA(){
        memset(dis,0x3f,sizeof(dis));
        int x,Low=INF;
        q.push_back(s);dis[s]=0;pre[s]=pre[t]=-1;
        while(!q.empty()){
            x=q.front();q.pop_front();inq[x]=false;
            for(int point=head[x];point!=-1;point=then)
                if(www && dis[now]>dis[x]+ccc){
                    dis[now]=dis[x]+ccc;pre[now]=point^1;
                    if(!inq[now]){
                        if(q.empty() || dis[q.front()]>dis[now])
                            q.push_front(now);
                        else
                            q.push_back(now);
                        inq[now]=true;
                    }
                }
        }
        if(pre[t]<0) return false;
        for(int point=pre[t];point!=-1;point=pre[now])
            Low=min(Low,node[point^1].low);
        for(int point=pre[t];point!=-1;point=pre[now])
            node[point^1].low-=Low,www+=Low;
        ans+=dis[t]*Low;
        return true;
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("1070.in","r",stdin);
        freopen("1070.out","w",stdout);
    #endif
    
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
        t=n*(m+1)+1;
        for(int i=s;i<=t;i++) head[i]=-1;
        for(int i=1;i<=n;i++) add(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++)
                    add(i,j*n+k,1,k*a[i][j]);
        for(int i=n+1;i<t;i++) add(i,t,1,0);
        while(SPFA());
        printf("%.2lf",(double)ans/n);
        return 0;
    }
    View Code
  • 相关阅读:
    Qt之自定义托盘(二)
    使用react-navigation提示undefind is not a function
    vue使用mockjs配置步骤(无需启动node服务)
    input框type=file设置cursor:pointer的问题
    umi中使用scss
    umi怎么去添加配置式路由
    Rem自适应js
    解决在antd中使用 autoprefixer 9.4.5 会抛出错误 Replace text-decoration-skip: ink to text-decoration-skip-ink: auto, because spec had been changed 的问题
    file类型input框设置上传相同文件,并都可以触发change事件。
    浅谈JavaScript对象数组根据某属性sort升降序排序
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/5227709.html
Copyright © 2020-2023  润新知