首页 > 其他分享 >P6577 【模板】二分图最大权完美匹配 (KM)

P6577 【模板】二分图最大权完美匹配 (KM)

时间:2024-05-14 12:09:22浏览次数:19  
标签:ch int long while P6577 KM 模板 getchar

$\quad $ 初看就发现不对劲了,模板紫题,一看就不简单,就交了个裸\(KM\),哎,果然\(T\)了。

$\quad $ 然后就是大力卡常(当然\(O(n^4)\))的复杂度不是卡常能解决的。遂看题解,发现一个据说\(O(n^3)\)的复杂度的\(KM\),也是非常抽象。
具体解释详见 https://www.luogu.com.cn/article/ip2m1gut

$\quad $ 当我还在研究题解的时候\(luobutianle\)直接就是溜过来跟我说倒着遍历可以起飞。我当时就是蒙,他就直接让我试了试,也是确实起飞了。

$\quad $ 大抵是造数据的人想卡\(KM\),认为人们都是正着遍历,就正着卡了。

献上我的大力卡常代码(当然过了)

点击查看代码
  #include<bits/stdc++.h>
  using namespace std;
  #define int long long
  const int N=550,M=250500;
  int match[N],slack[N],a[N],b[N],w[N][N],n,m,vis[N],rnd;
  int r(){
  	int ans=0;bool f=0;char ch=getchar();
  	while(ch<'0' || ch>'9'){if(ch=='-')f=1;ch=getchar();}
  	while(ch>='0' && ch<='9'){ans=(ans<<1)+(ans<<3)+(ch^48);ch=getchar();}
  	return f?~ans+1:ans;
  }
  bool dfs(int x){
      for(int i=1;i<=n;i=-~i){
          if(vis[i]^rnd){
              if(!((a[x]+b[i])^w[x][i])){
                  vis[i]=rnd;
                  if(!match[i]||dfs(match[i])){
                      match[i]=x;
                      return true;
                  }
              }else slack[i]=min(slack[i],a[x]+b[i]-w[x][i]);
          }
      }
      return false;
  }
  void write(long long n){
  	if(n>9)write(n/10);
  	putchar(n%10+'0');
  }
  signed main(){
      freopen("1.in","r",stdin);
      n=r(),m=r();
      for(int i=0;i<=n;i=-~i){
          for(int j=0;j<=n;j=-~j){
              w[i][j]=-9999999999;
          }
      }
      for(int i=1;i<=m;i=-~i)
          w[r()][r()]=r();
      for(int i=0;i<=n;i=-~i)a[i]=-99999999999;
      for(int i=1;i<=n;i=-~i){
          for(int j=1;j<=n;j=-~j){
              a[i]=max(a[i],w[i][j]);
          }
      }
      for(int i=0;i<=n;i=-~i)slack[i]=99999999999;
      for(int i=n;i>=1;i--){
          while(1){
              rnd++;
              if(dfs(i))break;
              int d=1e18;
              for(int j=1;j<=n;j++)if(vis[j]^rnd)d=min(d,slack[j]),slack[j]=99999999999;
              for(int j=1;j<=n;j++)if(vis[j]==rnd)b[j]+=d,a[match[j]]-=d;
              a[i]-=d;
          }
      }
      int ans=0;
      for(int i=1;i<=n;i=-~i)
          ans+=a[i]+b[i];
      ans<0?putchar('-'),ans=-ans:0;
      write(ans);
      putchar('\n');
      for(int i=1;i<=n;i=-~i)write(match[i]),putchar(' ');
      return 0;
  }

还有优化代码:

点击查看代码
  #include<bits/stdc++.h>
  using namespace std;
  #define int long long
  const int N=550,M=250500;
  int match[N],slack[N],a[N],b[N];
  int vis[N],rnd,pre[N];
  bool vx[N],vy[N];
  int matchy[N],matchx[N];
  int w[N][N],n,m;
  queue<int>q;
  long long r(){
  	long long ans=0;bool f=0;char ch=getchar();
  	while(ch<'0' || ch>'9'){if(ch=='-')f=1;ch=getchar();}
  	while(ch>='0' && ch<='9'){ans=(ans<<1)+(ans<<3)+(ch^48);ch=getchar();}
  	return f?~ans+1:ans;
  }
  void fl(int x){
      int t;
      while(x){
          t=matchx[pre[x]];
          matchx[pre[x]]=x;
          matchy[x]=pre[x];
          x=t;
      }
      return;
  }
  void dfs(int l){
      memset(vx,0,sizeof vx);
      memset(vy,0,sizeof vy);
      memset(slack,0x7f,sizeof slack);
      while(q.size())q.pop();
      q.push(l);
      while(1){
          while(q.size()){
              int x=q.front();q.pop();
              vx[x]=1;
              for(int i=1;i<=n;i++){
                  if(vy[i]!=1){
                      if(a[x]+b[i]-w[x][i]<slack[i]){
                          slack[i]=a[x]+b[i]-w[x][i];
                          pre[i]=x;
                          if(!slack[i]){
                              vy[i]=1;
                              if(!matchy[i]){
                                  fl(i);
                                  return;
                              }else q.push(matchy[i]);
                          }
                      }
                  }
              }
          }
          int d=1e18;
          for(int i=1;i<=n;i++)if(vy[i]!=1)d=min(d,slack[i]);
          for(int i=1;i<=n;i++){
              if(vx[i]==1)a[i]-=d;
              if(vy[i]==1)b[i]+=d;
              else slack[i]-=d;
          }
          for(int i=1;i<=n;i++){
              if(vy[i]!=1){
                  if(!slack[i]){
                      vy[i]=1;
                      if(!matchy[i]){
                          fl(i);
                          return;
                      }else q.push(matchy[i]);
                  }
              }
          } 
      }
  }
  void wr(int x){
      if(x>9)wr(x/10);
      putchar(x%10+'0');
  }
  signed main(){
      n=r(),m=r();
      memset(w,0xcf,sizeof w);
      for(int i=1;i<=m;i++){
          w[r()][r()]=r();
      }
      memset(a,0xcf,sizeof a);
      for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
              a[i]=max(a[i],w[i][j]);
      for(int i=1;i<=n;i++)dfs(i);
      int ans=0;
      for(int i=1;i<=n;i++)ans+=a[i]+b[i];
      ans<0?putchar('-'),ans=-ans:0;
      wr(ans);putchar('\n');
      for(int i=1;i<=n;i++)wr(matchy[i]),putchar(' ');
      return 0;
  }

标签:ch,int,long,while,P6577,KM,模板,getchar
From: https://www.cnblogs.com/0shadow0/p/18191040

相关文章

  • Vue模板语法、属性绑定、条件渲染的学习
    Vue模板语法:使用插值表达式的内容必须是有结果的内容才可以,就是需要return出来的才可以显示出来。插值表达式所表现的内容为纯文本模式如何避免即所有的逻辑操作都在js里面实现,不要再templete中实现可以完美的避免这个问题。Vue属性绑定1.使用v-bind进行属性绑定语法:v-b......
  • 一些模板
    之前的模板在我考研时脑子一热删掉了QAQ,现在重新写了点,Python和C++都有。dijkstra\(O(n^2)\)importosimportsysimportmathimportcopyfromcollectionsimportdequefromheapqimport*sys.setrecursionlimit(30000)MAXN=1<<32n,m,st=map(int,input().......
  • 低开开发笔记(六): 工作台与模板样式开发
    好家伙,仅仅只是实现了样式,完整功能暂未完成 完整代码已开源https://github.com/Fattiger4399/ph-questionnaire.git  1.灵感来源(抄袭对象)刚开始想着随便写个低开项目练练手的,然后就写成这样了1.1.简道云 1.2.问卷星  2.上代码<template><divc......
  • 【VMware vSphere】如何查看 OVF/OVA 模板部署虚拟机所配置的密码。
    当我们从OVF/OVA模板部署虚拟机时,在部署期间可能会要求你对虚拟机进行一些配置,比如IP地址、虚拟机密码等。关于这些配置参数,登录vSphereClient,可以转到该虚拟机-配置-设置-vApp选项-属性中进行参看。当我们部署完这个虚拟机后,如果长时间没有登录,忘记配置期间设置的密码,那该怎......
  • EPAI手绘建模APP工程图模板、投影、剖切、局部放大、中间线、符号、填充
    (4) 工程图① 模板1) 模板包括可以选择修改的模板字段和不可选择修改的固定元素。2) 选择模板字段长按,打开模板字段编辑器,填写模板字段内容,点击工程图空白地方,更新模板字段。图 314 工程图元素编辑器-模板字段② 工程图元素1) 投影a. 选择投影,长按,打开投影元素编......
  • Spring6 的JdbcTemplate的JDBC模板类的详细使用说明
    1.Spring6的JdbcTemplate的JDBC模板类的详细使用说明@目录1.Spring6的JdbcTemplate的JDBC模板类的详细使用说明每博一文案2.环境准备3.数据准备4.开始4.1从数据表中插入(添加)数据4.2从数据表中修改数据4.3从数据表中删除数据4.4从数据表中查询一个对象4.5从数据表中......
  • 记字符串匹配KMP算法
    字符串匹配是一类经典的问题,在字符串s中找出模式串t第一个元素的下标,如果没有匹配到,则返回-1。此问题在leetcode中甚至归类为简单。解决此问题最直接的思路是使用暴力解法,从第0个元素开始逐个比较元素,当字符不匹配时,s的指针向前移动一位,不断重复。这种思路最简单且直接,但是无法通......
  • 匈牙利算法模板(二分图)
    booldfs(intnow){for(inti=h[now];i;i=nxt[i]){intt=to[i];//这里不用考虑会有回到父结点的边的问题//因为每次都是从左部找邻接点if(!vis[t]){vis[t]=true;//如果邻接点t是非匹配点,则找到一条增广路,匹配......
  • BMP的结构体定义模板
    /****BMP文件头数据结构****/typedefstruct{unsignedchartype[2];//文件类型unsignedintsize;//文件大小unsignedshortreserved1;//保留字段1unsignedshortreserved2;//保留字段2unsignedintoffset;//......
  • P3387 【模板】缩点
    求DAG中一条最大点权链用scc缩点完成后其实问题就回到了DAG,这样一个问题,开始dfs写多了,直接找入度为0为起点一个dfs,结果就搜爆了。正解:寻找DAG中一个拓扑排序,按照拓扑序遍历点,再遍历点的边,dp维护答案而Tarjan缩点完成后新点的倒序(ans_scc->1)就是一个拓扑序,于......