• 【BZOJ3996】[TJOI2015]线性代数(最小割)


    【BZOJ3996】[TJOI2015]线性代数(最小割)

    题面

    BZOJ
    洛谷

    题解

    首先把式子拆开,发现我们的答案式就是这个:

    [sum_{i=1}^nsum_{j=1}^n B_{i,j}A_iA_j-sum_{i=1}^n A_iC_i ]

    发现(A)(01)矩阵,再结合数据范围一脸一个最大权闭合子图的形式。
    然后这里有两种做法,
    第一种是无脑版本,对于每个(B_{i,j})都建立一个新点。
    第二种就手动解一下方程,点数稍微少点,边数一样。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define MAX 300000
    const int inf=1e9;
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    struct Line{int v,next,w;}e[MAX*10];
    int h[MAX],cnt=2;
    inline void Add(int u,int v,int w)
    {
    	e[cnt]=(Line){v,h[u],w};h[u]=cnt++;
    	e[cnt]=(Line){u,h[v],0};h[v]=cnt++;
    }
    int S,T,level[MAX],cur[MAX];
    bool bfs()
    {
    	for(int i=S;i<=T;++i)level[i]=0;
    	queue<int> Q;Q.push(S);level[S]=1;
    	while(!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for(int i=h[u];i;i=e[i].next)
    			if(e[i].w&&!level[e[i].v])
    				level[e[i].v]=level[u]+1,Q.push(e[i].v);
    	}
    	return level[T];
    }
    int dfs(int u,int flow)
    {
    	if(u==T||!flow)return flow;
    	int ret=0;
    	for(int &i=cur[u];i;i=e[i].next)
    	{
    		int v=e[i].v;
    		if(level[v]==level[u]+1)
    		{
    			int d=dfs(v,min(flow,e[i].w));
    			ret+=d;flow-=d;
    			e[i].w-=d;e[i^1].w+=d;
    		}
    	}
    	if(!ret)level[u]=0;
    	return ret;
    }
    int Dinic()
    {
    	int ret=0;
    	while(bfs())
    	{
    		for(int i=S;i<=T;++i)cur[i]=h[i];
    		ret+=dfs(S,inf);
    	}
    	return ret;
    }
    int n,C[505],B[505][505],ans,tot;
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n;++j)ans+=(B[i][j]=read());
    	for(int i=1;i<=n;++i)C[i]=read();
    	S=0;T=n+n*n+1;tot=n;
    	for(int i=1;i<=n;++i)Add(S,i,C[i]);
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n;++j)
    		{
    			++tot;
    			Add(i,tot,inf);Add(j,tot,inf);
    			Add(tot,T,B[i][j]);
    		}
    	printf("%d
    ",ans-Dinic());
    	return 0;
    }
    
  • 相关阅读:
    linux 切换图形界面
    google浏览器插件源码目录查询
    subline注册码
    mongodb数组多值查询(条件:数据库中必须包含条件信息)
    SpringBoot多数据源解决方案(转载)
    腾讯云服务器做代理
    多线程经典问题顺序打印
    flume 1.7在windows下的安装部署与测试运行
    解决spring-boot-maven-plugin插件打包,springboot启动时报找不到主main问题
    MYSQL的B+Tree索引树高度如何计算
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10757246.html
Copyright © 2020-2023  润新知