zoukankan      html  css  js  c++  java
  • [SCOI2007] 修车

    题目链接:戳我

    比较套路,就是把每个工人拆成n个,来一一对应第i个工人修倒数第j辆车的状态。

    我们很容易可以发现,如果一个工人x修n辆车的话,顾客的等待时间总和应该是修倒数第一辆车的时间( imes) 1+修倒数第二辆车的时间( imes) 2+...+修倒数第n辆车的时间( imes) n。

    现在大家应该明白为什么拆点的时候表示的意义不是正着来的,而是倒数第几辆车——因为我们无法知道一个工人在最优策略中一共修多少车,所以算总时间的时候乘上的系数是未知的。但是我们可以倒着过来,然后跑费用流,这样如果后面他没有修到的话,自然就不会算到最优解情况里面了,

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define MAXN 1010
    #define S 0
    #define T n+m*n+1
    using namespace std;
    int n,m,t=1,c,f;
    int ti[MAXN][MAXN],dis[MAXN],done[MAXN],pre_e[MAXN],pre_v[MAXN],head[MAXN];
    struct Edge{int nxt,to,dis,cost;}edge[200010];
    inline void add(int from,int to,int dis,int cost)
    {	
    	edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,edge[t].cost=cost,head[from]=t;
    	edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=0,edge[t].cost=-cost,head[to]=t;
    }
    inline bool spfa()
    {
    	queue<int>q;
    	memset(dis,0x3f,sizeof(dis));
    	q.push(S);done[S]=1;dis[S]=0;
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();done[u]=0;
    		for(int i=head[u];i;i=edge[i].nxt)
    		{
    			int v=edge[i].to; 
    			if(dis[u]+edge[i].cost<dis[v]&&edge[i].dis)
    			{
    				dis[v]=dis[u]+edge[i].cost;
    				pre_e[v]=i,pre_v[v]=u;
    				if(!done[v]) q.push(v),done[v]=1;
    			}
    		}
    	}
    	if(dis[T]==0x3f3f3f3f) return false;
    	int flow=(int)1e9;
    	for(int i=T;i!=S;i=pre_v[i]) flow=min(flow,edge[pre_e[i]].dis);
    	for(int i=T;i!=S;i=pre_v[i]) edge[pre_e[i]].dis-=flow,edge[pre_e[i]^1].dis+=flow;
    	c+=flow*dis[T];
    	f+=flow;
    	return true;
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
    	scanf("%d%d",&m,&n);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			scanf("%d",&ti[i][j]);
    	for(int i=1;i<=n;i++) add(S,i,1,0);
    	for(int i=1;i<=m;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			add((i-1)*n+n+j,T,1,0);
    			for(int k=1;k<=n;k++)
    				add(k,(i-1)*n+n+j,1,ti[k][i]*j);
    		}
    	}
    	while(spfa());
    	printf("%.2lf
    ",1.0*c/n);
    	return 0;
    }
    
  • 相关阅读:
    cgal 的初步学习
    java 代理类
    java 静态内部类
    HDU-2063-过山车(最大匹配)
    HDU-1845-Jimmy's Assignment
    HDU-1528-Card Game Cheater(二分图匹配)
    HDU-1507-Uncle Tom's Inherited Land*
    HDU-1498-50years,50colors(最大匹配, 枚举)
    HDU-1281-棋盘游戏(最大匹配,枚举)
    HDU-1179-Ollivanders(二分图最大匹配)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10335813.html
Copyright © 2011-2022 走看看