bzoj1070(修车)(费用流)

建图重要。

m个工人, n辆车

源点向每辆车连一条容量为1费用为0的边。

把每个工人拆成n个,第i个工人的第j个节点表示,第i个工人修倒数j辆车。

每辆车向这n*m个工人连一条容量为1费用为这个工人修这辆车的时间*这个工人倒数第几个修这辆车。

因为修一辆车只会使在它后面修的都+修这辆车的时间。

//我服了,烂费用流板子,一直t,狗了一个别人的spfa,才过。我就吐槽一句,是谁教我的费用流!?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int n, m, shi[15][65], huan, hui,tot;
int tp = 1,  dis[100000],  vis[100000], tov[100000], tof[100000], tow[100000], h[100000], nex[100000], fa[100000], bian[100000];
double ans;
deque<int> q;
void read(int &x)
{
	x = 0;
	int f = 0;
	 char c = getchar();
	 while(c < '0' || c > '9')
	 {
	 	if(c == '-')  f = 1; 
		 c = getchar();
	 }
	 while(c >= '0' && c <= '9')
	 {
	 	x = x * 10 + c - '0';
	 	c = getchar();
	 }
	 if(f) x = -x;
}
void add(int x,int y,int w,int f)
{
	tp++;
	tov[tp] = y;
	tow[tp] = w;
	tof[tp] = f;
	nex[tp] = h[x];
	h[x] = tp;

    tp++;
    tov[tp] = x;
    tow[tp] = 0;
    tof[tp] = -f;
    nex[tp] = h[y];
    h[y] = tp;
}
/*bool spfa()
{
	memset(dis,0x3f3f3f3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(q,0,sizeof(q));
	int head = 0, tail = 1;
	dis[huan] = 0; 
    q[tail] = huan;
	vis[huan] = 1;
	while(head < tail)
	{
		head++;
		int x = q[head];
		for(int i = h[x]; i; i = nex[i])
		{
			tot++;
			int v = tov[i];
			if(dis[v] > dis[x] + tof[i] && tow[i] != 0)
			{
				dis[v] = dis[x] + tof[i];
				fa[v] = x;
				bian[v] = i;
				if(vis[v] == 0)
				{
					vis[v] = 1;
					tail++;
					q[tail] = v;
				}
			}
		}
		vis[x] = 0;
	   } 
	   return dis[hui] == dis[hui+1] ? 0 : 1;   
}
*/
bool spfa(int s,int e)
{
    memset(dis,63,sizeof(dis));
    dis[s] = 0;
    vis[s] = 1;
    q.push_front(s);
    while(q.size())
    {
        int f = q.front(); q.pop_front();
        vis[f] = 0;
        for(int i = h[f];i;i = nex[i])
        {
            int v = tov[i];
            if(tow[i] && dis[v] > dis[f] + tof[i])
            {
                dis[v] = dis[f] + tof[i];
                bian[v] = i;
                fa[v]= f;
                if(!vis[v])
                {
                    vis[v] = 1;
                    if(q.empty() || dis[v] < dis[q.front()])
                        q.push_front(v);
                    else
                        q.push_back(v);
                }
            }
        }
    }
    if(dis[e] == dis[e+2]) return false;
    return true;
}
int liu()
{
int u=hui;
int delta=1e9;
while(u!=huan)
{
	delta=min(delta,tow[bian[u]]);
	u=fa[u];
}
u=hui;
while(u!=huan)
{
	tow[bian[u]]-=delta;
	tow[bian[u]^1]+=delta;
	u=fa[u];
}
return dis[hui];
}
int main()
{
	int haha = 1; 
	read(m);read(n);
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		read(shi[j][i]);
	}
	huan = 0;
	hui = n + m * n + 1;
	for(int i = 1; i <= n; i++)
	{
		add(huan, 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,n+(j-1)*n+k,1,k * shi[j][i]);
	}
	for(int i = 1; i <= m; i++)
	 for(int j = 1; j <= n; j++)
	 add(n+(i-1)*n + j, hui,1,0);
	 while(spfa(huan,hui))
	 {
	 	ans += liu();
	 }
	 printf("%0.2lf",ans/n);
	 //cout <<tot ;
	 return 0;
 } 

猜你喜欢

转载自blog.csdn.net/Bluelanzhan/article/details/83551839
今日推荐