zoukankan      html  css  js  c++  java
  • [luoguP2053] [SCOI2007]修车(最小费用最大流)

    传送门

    网络流的建图真的好难!

    将一个点拆分成多个点的思想还需要加强。

    题解

    代码和题解中的图略不一样。

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define N 1000001
    
    using namespace std;
    
    int n, m, cnt, s, t;
    int head[N], to[N], nex[N], val[N], cost[N], dis[N], pre[N], path[N];
    bool vis[N];
    double tim;
    
    inline int read()
    {
    	int x = 0, f = 1;
    	char ch = getchar();
    	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
    	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
    	return x * f;
    }
    
    inline void add(int x, int y, int z, int v)
    {
    	to[cnt] = y;
    	val[cnt] = z;
    	cost[cnt] = v;
    	nex[cnt] = head[x];
    	head[x] = cnt++;
    }
    
    inline bool spfa()
    {
    	int i, u, v;
    	queue <int> q;
    	memset(vis, 0, sizeof(vis));
    	memset(pre, -1, sizeof(pre));
    	memset(dis, 127, sizeof(dis));
    	q.push(s);
    	dis[s] = 0;
    	while(!q.empty())
    	{
    		u = q.front();
    		vis[u] = 0;
    		q.pop();
    		for(i = head[u]; ~i; i = nex[i])
    		{
    			v = to[i];
    			if(val[i] && dis[v] > dis[u] + cost[i])
    			{
    				dis[v] = dis[u] + cost[i];
    				pre[v] = u;
    				path[v] = i;
    				if(!vis[v])
    				{
    					q.push(v);
    					vis[v] = 1;
    				}
    			}
    		}
    	}
    	return pre[t] != -1;
    }
    
    int main()
    {
    	int i, j, k, x, f;
    	m = read();
    	n = read();
    	s = 0, t = n + n * m + 1;
    	memset(head, -1, sizeof(head));
    	for(i = 1; i <= n; i++)
    		for(j = 1; j <= m; j++)
    		{
    			x = read();
    			for(k = 1; k <= n; k++)
    			{
    				add((k - 1) * m + j, i + n * m, 1, k * x);
    				add(i + n * m, (k - 1) * m + j, 0, -k * x);
    			}
    			add(s, j + (i - 1) * m, 1, 0);
    			add(j + (i - 1) * m, s, 0, 0);
    		}
    	for(i = 1; i <= n; i++)
    	{
    		add(i + n * m, t, 1, 0);
    		add(t, i + n * m, 0, 0);
    	}
    	while(spfa())
    	{
    		f = 1e9;
    		for(i = t; i != s; i = pre[i]) f = min(f, val[path[i]]);
    		tim += dis[t];
    		for(i = t; i != s; i = pre[i])
    		{
    			val[path[i]] -= f;
    			val[path[i] ^ 1] += f;
    		}
    	}
    	printf("%.2lf
    ", double(tim / n));
    	return 0;
    }
    

      

  • 相关阅读:
    GNU KHATA——开源的会计管理软件
    Web服务精讲–搭个 Web 服务器(二)
    据说Linuxer都难忘的25个画面
    谷歌开源运作解密
    实战Centos系统部署Codis集群服务
    这些被称为史上最 “贱” 黑客
    Linux 利器- Python 脚本编程入门(一)
    在 Ubuntu 16.04 上安装 LEMP 环境之图文向导
    Linux下6种优秀的邮件传输代理
    移动互联网期末笔记
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/8249577.html
Copyright © 2011-2022 走看看