首页 > 其他分享 >BZOJ 3996: [TJOI2015]线性代数 最大权闭合子图 最小割

BZOJ 3996: [TJOI2015]线性代数 最大权闭合子图 最小割

时间:2023-07-07 13:31:50浏览次数:46  
标签:ch 矩阵 点权 子图 TJOI2015 3996 include 割掉



3996: [TJOI2015]线性代数



Time Limit:  10 Sec   Memory Limit:  128 MB



Submit:  1499   Solved:  885



[ Submit ][ Status ][ Discuss ]

Description



给出一个N*N的矩阵B和一个1*N的矩阵C。求出一个1*N的01矩阵A.使得



D=(A*B-C)*A^T最大。其中A^T为A的转置。输出D






Input



第一行输入一个整数N,接下来N行输入B矩阵,第i行第J个数字代表Bij.



接下来一行输入N个整数,代表矩阵C。矩阵B和矩阵C中每个数字都是不超过1000的非负整数。




Output



输出最大的D




Sample Input



3



1 2 1



3 1 0



1 2 3



2 3 7



Sample Output



2



HINT



 1<=N<=500



看完题之后,推了好久式子,然而,只是在浪费时间 括弧泪
找题解
Wa!!怎么是网络流!!最大权闭合子图  ,我果然还是太蒟蒻了 括弧泪
那么既然学会了,就应该写一篇高质量的博客



我们发现:
如果想取B[i][j]那么一定要保证a[i]、a[j]都为1,a[i]、a[j]都为1,则c[i],c[j]就都要取



那么把它们抽象成点,对于一个点,向必须与它同时选的点连边



并且点具有点权(此题中,B中的点权为正1,C中的为负)
所以它的最大权闭合子图就是要求的解
现在就来说一些关于最大全闭合子图的东西



材料来自:传送门



现在有一个有向图,每个点有点权,点权可正可负。



对于任意一条有向边i和j,选择了点i就必须选择点j, 你需要选择一些点使得得到权值最大。
这个问题可以用网络流解决。 
建图方法:对于任意点i,如果i权值为正,s向i连容量为其权值的边,



否则i向t连容量为其权值的绝对值的边。



原图所有边容量为正无穷。则最大权=正权和-最大流。 
如何证明呢?我们把最大流理解成最小割,那么割掉的边一定不可能是正无穷的边。 
我们发现,选择一个正权点即不割掉s到其的边,选择一个负权点即割掉其到t的边。 



现在证明方案合法:



对于依赖关系i到j: 
假设i点权为正j点权为负。



选了i不选j即没有割掉s到i的边而且没有割掉j到t的边,显然s和t联通,不符合最小割定义。 
假设i点权为负j点权为正。



选了i不选j即割掉i到t的边而且割掉s到j的边,由于s到t现在不连通,我们不割



这两条边同样s和t是不联通的,那么割这两边不满足割量最小,不符合最小割定义。 
其余情况同理,不符合割量最小。 
注意这个算法不需要原图是DAG。




#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f*x;
}
const int N=3000000;const int inf=0X3f3f3f3f;
int n,m,ecnt=1,last[N],cur[N],q[N],d[N],S,T=N-10,ans;
struct EDGE{int to,nt,val;}e[N];
inline void readd(int u,int v,int val)
{e[++ecnt]=(EDGE){v,last[u],val};last[u]=ecnt;}
inline void add(int u,int v,int val)
{readd(u,v,val);readd(v,u,0);}
bool bfs()
{
    memset(d,0,sizeof(d));
    d[S]=1;int head=0,tail=1;q[0]=S;
    while(head<tail)
    {
        int u=q[head++];
        for(int i=last[u];i;i=e[i].nt)
        if(e[i].val&&!d[e[i].to])
        {
            d[e[i].to]=d[u]+1;
            q[tail++]=e[i].to;
        }
    }
    return d[T];
}
int dfs(int u,int limit)
{
    if(u==T||!limit)return limit;
    int flow=0;
    for(int i=cur[u];i;i=e[i].nt)
    if(e[i].val&&d[u]+1==d[e[i].to])
    {
        int tmp=dfs(e[i].to,min(e[i].val,limit));
        e[i].val-=tmp;e[i^1].val+=tmp;flow+=tmp;limit-=tmp;
        if(e[i].val)cur[u]=i;if(!limit)break;
    }
    if(!flow)d[u]=-1;
    return flow;
}
inline void dinic()
{while(bfs()){for(int i=0;i<=n*n+n;i++)cur[i]=last[i];cur[T]=last[T];ans-=dfs(S,inf);}}
int main()
{
    n=read();int tmp=n,temp;
    for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
    {
        temp=read();ans+=temp;
        add(S,++tmp,temp);
        add(tmp,i,inf);add(tmp,j,inf);
    }
    for(int i=1;i<=n;i++)
    {temp=read();add(i,T,temp);}
    dinic();
    printf("%d\n",ans);
    return 0; 
}




标签:ch,矩阵,点权,子图,TJOI2015,3996,include,割掉
From: https://blog.51cto.com/u_16181403/6652027

相关文章

  • P3975 [TJOI2015] 弦论 题解
    一、题目描述:给你一个长度为$n$的字符串,字符串由$26$个小写字母组成,求第$k$大的字串。给定参数$t$:$t=0:\位置不同的相同字串只算一个。$$t=1:\位置不同的相同字串算作多个。$若字串数量不足$k$个,输出$-1$。数据范围:$1\le......
  • 【Python】在同一图形中更加优雅地绘制多个子图
    1.引言数据可视化非常重要,有一句俗语叫做一图顶千言,我相信好多小伙伴应该都听说过这句话;即使是有人第一次听到,我想应该也会觉得赞成,这足以说明数据可视化的重要性。我们在前一篇博客中,介绍了如何利用subplot来在一张子图里绘制多个子图,最近我又发现了一种更加优雅地实现,迫不及待地......
  • 【Python】在同一图形中的绘制多个子图
    1.引言有时我们需要并排绘制两个图形,这不仅是为了更好地利用空间,而且主要是因为为了更加直观地对比分析数据。其实在python中可以利用subplot来实现上述功能。闲话少说,我们直接开始吧!2.准备工作这里,我们不妨先来举个例子,比方说,我们正在分析一家出租车公司的出行分布,假设我们想知......
  • 【QoS预测】用于冷启动QoS预测的基于图对比学习的双子图网络
    论文题目:ZhuJ,LiB,WangJ,etal.BGCL:Bi-subgraphnetworkbasedongraphcontrastivelearningforcold-startQoSprediction[J].Knowledge-BasedSystems,2023,263:110296.问题:通过利用用户和服务之间的历史交互记录,协同过滤(Collaborativefiltering)成为了一种......
  • python · matplotlib | 如何绘制子图
    代码:importmatplotlib.pyplotaspltimportmatplotlibmatplotlib.rc("font",family='MicroSoftYaHei',weight="bold")fig,axs=plt.subplots(2,2,figsize=(15,12))colors=['blue','orange','green&#......
  • Luogu P3978 [TJOI2015] 概率论
    定义\(f_i\)为\(i\)个节点组成的二叉树数量,\(g_i\)为\(i\)个节点组成的二叉树的叶子节点个数之和设当前\(i\)个节点组成的二叉树有\(a\)个叶子,容易发现分别删掉其中的\(1\)个叶子节点就能得到一个对应的\(i-1\)个节点的二叉树,总共会有\(a\)颗,可以发现每一个叶......
  • CINN 中子图编译缓存机制
    采用「问-答」形式记录研读CINN开源框架的笔记Q:CINN中子图编译的入口是在哪里?for(constauto&node_vec:clusters){//<-------逐个遍历每个子图//Classifyvarnodetoinputs,outputs,andinternals.GraphNodeSetcluster_set(node_vec.begin(),n......
  • 最大权闭合子图
    最大权闭合子图一、概念闭合子图给定一个有向图\(G(V,E)\),图中的某一个点集,这个点集满足内部的所有边不能从点集里面指向点集外面,则将这个点集和点集里面的边统称为原图的闭合子图最大权闭合子图给定一个有向图\(G(V,E)\),每个点上有一个权值,图中存在若干个闭合子图,若其中一......
  • 量子图形加密算法的MATLAB代码实现
    一、概述目前主流的量子图形加密算法有量子像素编码算法(QuantumImagePixelEncoding,QIPE)、量子像素置乱算法(QuantumImagePixelScrambling,QIPS)等。一个简......
  • 最大权闭合子图
    前置知识:最大权闭合子图。这是个什么东东呢,它是对于每一个点赋一个值,求一个点集,点集内的所有点都必须包含它的所有后继,使这个点集的和最大。如以下图:图中的编号代表点......