• 【六省联考2017】寿司餐厅


    题面

    题解

    有经验的选手可以根据权值不重复计算的特性看出这是一个最大权闭合子图问题;

    我看了题解就知道这是一个最大权闭合子图问题。。。

    建边:

    1. 对于所有的区间$[i,j]$的收益,将它们都看成点

      如果权值为正,从源点连来,容量为权值

      否则连向汇点,容量为权值的绝对值

    2. 将区间$[i,j]$,向区间内$i,j$连边,容量为$infty$,表示选对应的寿司就选对应的区间

    3. 对于所有寿司类型$a[i]$,将它们向汇点连边,容量为$m imes a[i]^2$

    4. 对于每一个寿司,向它们所属类型连边,容量$infty$,向汇点连边,容量为$a[i]$

    5. 对于所有的$[i,j]$区间,向$[i + 1,j]$和$[i, j - 1]$,容量为$infty$,表示选了大区间肯定选其中的小区间

    $ans$就是总收益减去最小割就可以了

    代码

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #define RG register
    #define clear(x, y) memset(x, y, sizeof(x))
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while(ch != '-' && (!isdigit(ch))) ch = getchar();
    	if(ch == '-') w = -1, ch = getchar();
    	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    const int maxn(40010), maxm(110), INF(0x3f3f3f3f);
    struct edge { int next, to, cap; } e[maxn << 6];
    int head[maxn], cur[maxn], e_num = -1;
    inline void add_edge(int from, int to, int cap)
    {
    	e[++e_num] = (edge) {head[from], to, cap}; head[from] = e_num;
    	e[++e_num] = (edge) {head[to], from,  0 }; head[to]   = e_num;
    }
    
    bool bfs();
    int dfs(int x, int f);
    inline int Dinic();
    int n, m, a[maxm], g[maxm][maxm];
    int id[maxm][maxm], ida[maxn], idp[maxm], S, T;
    long long ans;
    
    void init_id()
    {
    	int idcnt = 0; S = ++idcnt;
    	for(RG int i = 1; i <= n; i++)
    		for(RG int j = i; j <= n; j++)
    			id[i][j] = ++idcnt;
    	for(RG int i = 1; i <= n; i++) if(!ida[a[i]]) ida[a[i]] = ++idcnt;
    	for(RG int i = 1; i <= n; i++) idp[i] = ++idcnt;
    	T = ++idcnt;
    }
    
    void build_edge()
    {
    	static bool vis[maxn]; clear(vis, 0); init_id();
    	for(RG int i = 1; i <= n; i++)
    		if(!vis[a[i]])
    		{
    			vis[a[i]] = true;
    			add_edge(ida[a[i]], T, m * a[i] * a[i]);
    		}
    	for(RG int i = 1; i <= n; i++)
    		add_edge(idp[i], ida[a[i]], INF),
    		add_edge(idp[i], T, a[i]);
    	for(RG int i = 1; i <= n; i++)
    		for(RG int j = i; j <= n; j++)
    		{
    			if(g[i][j] > 0)
    			{
    				ans += g[i][j];
    				add_edge(S, id[i][j], g[i][j]);
    			}
    			else if(g[i][j] < 0) add_edge(id[i][j], T, -g[i][j]);
    			add_edge(id[i][j], idp[i], INF);
    			add_edge(id[i][j], idp[j], INF);
    			if(i != j)
    				add_edge(id[i][j], id[i + 1][j], INF),
    				add_edge(id[i][j], id[i][j - 1], INF);
    		}
    }
    
    int main()
    {
    	clear(head, -1); n = read(), m = read();
    	for(RG int i = 1; i <= n; i++) a[i] = read();
    	for(RG int i = 1; i <= n; i++)
    		for(RG int j = i; j <= n; j++) g[i][j] = read();
    	build_edge();
    	printf("%lld
    ", ans - Dinic());
    	return 0;
    }
    
    /**************** Dinic ******************/
    inline int Dinic()
    {
    	int res = 0;
    	while(bfs())
    	{
    		for(RG int i = S; i <= T; i++) cur[i] = head[i];
    		res += dfs(S, INF);
    	}
    	return res;
    }
    
    int lev[maxn], q[maxn], tail;
    bool bfs()
    {
    	clear(lev, 0);
    	q[tail = lev[S] = 1] = S;
    	for(RG int i = 1; i <= tail; i++)
    	{
    		int x = q[i];
    		for(RG int j = head[x]; ~j; j = e[j].next)
    		{
    			int to = e[j].to; if(lev[to] || (!e[j].cap)) continue;
    			q[++tail] = to, lev[to] = lev[x] + 1;
    		}
    	}
    	return lev[T];
    }
    
    int dfs(int x, int f)
    {
    	if(x == T || (!f)) return f;
    	int ans = 0, cap;
    	for(RG int &i = cur[x]; ~i; i = e[i].next)
    	{
    		int to = e[i].to;
    		if(e[i].cap && lev[to] == lev[x] + 1)
    		{
    			cap = dfs(to, std::min(f - ans, e[i].cap));
    			e[i].cap -= cap, e[i ^ 1].cap += cap;
    			ans += cap; if(ans == f) break;
    		}
    	}
    	return ans;
    }
    
  • 相关阅读:
    BigInteger与BigDecimal
    Java常用类之时间类
    Java常用类之字符串类
    单例对象 (Singleton)设计模式
    包装类的使用
    Object 类中的主要结构
    PostgreSQL执行计划的解析
    Redis5.0 配置文件中文参考
    jvm系列(六):jvm调优-工具篇
    5,Spark中文件格式、压缩和序列化
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10254713.html
Copyright © 2020-2023  润新知