bzoj1070 [SCOI2007]修车 费用流

分析:巧妙构图,记得某一次bc的最后一道题就是这个,就是借鉴这个老题吧,貌似很多题都是借鉴这个题

        关键在于,倒着看是某个人倒数第几个修,这样只影响后面的人,跑费用流就好了

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn=1200;
const int INF=0x3f3f3f3f;
struct Edge
{
    int from,to,cap,flow,cost;
    Edge(int u,int v,int c,int d,int p):from(u),to(v),cap(c),flow(d),cost(p) {}
};
struct MCMF
{
    int s,t,flow,cost;
    vector<Edge>edges;
    vector<int>G[maxn];
    int inq[maxn];
    int d[maxn];
    int p[maxn];
    int a[maxn];
    void init()
    {
        for(int i=0;i<maxn;i++)
        G[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int cap,int cost)
    {
        edges.push_back((Edge){from,to,cap,0,cost});
        edges.push_back((Edge){to,from,0,0,-cost});
        int l=edges.size();
        G[from].push_back(l-2);
        G[to].push_back(l-1);
    }
    bool BellmanFord(int s,int t)
    {
       for(int i=0;i<maxn;i++)
        d[i]=INF;
       memset(inq,0,sizeof(inq));
       d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;
       queue<int>Q;
       Q.push(s);
       while(!Q.empty())
       {
          int u=Q.front();
          Q.pop();
          inq[u]=0;
          for(int i=0;i<G[u].size();i++)
          {
              Edge &e=edges[G[u][i]];
              if(e.cap>e.flow&&d[e.to]>d[u]+e.cost)
              {
                 d[e.to]=d[u]+e.cost;
                 p[e.to]=G[u][i];
                 a[e.to]=min(a[u],e.cap-e.flow);
                 if(!inq[e.to])
                 {
                     Q.push(e.to);
                     inq[e.to]=1;
                 }
              }
          }
       }
       if(d[t]==INF)return false;
       flow+=a[t];
       cost+=d[t]*a[t];
       int u=t;
       while(u!=s)
       {
           edges[p[u]].flow+=a[t];
           edges[p[u]^1].flow-=a[t];
           u=edges[p[u]].from;
       }
       return true;
    }
    int Mincost(int s,int t)
    {
        flow=cost=0;
        while(BellmanFord(s,t));
        return cost;
    }
}solve;
int c[65][65];
int main(){
  int m,n;
  scanf("%d%d",&m,&n);
  for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)
      scanf("%d",&c[i][j]);
  solve.init();  
  for(int i=1;i<=n;++i){
    for(int j=1;j<=m;++j){
      for(int k=1;k<=n;++k){
        int pos=(j-1)*n+k;
        solve.AddEdge(i+n*m,pos,1,k*c[i][j]);
      }
    } 
  }
  for(int i=1;i<=n;++i)solve.AddEdge(0,i+n*m,1,0);
  for(int i=1;i<=n*m;++i)solve.AddEdge(i,n+n*m+1,1,0);
  printf("%.2f\n",1.0*solve.Mincost(0,n+n*m+1)/n);
  return 0;
}
View Code

 

posted @ 2016-08-31 18:39  shuguangzw  阅读(187)  评论(0编辑  收藏  举报