【UOJ 80】 二分图最大权匹配

【分析】

  之前打的那种KM会TLE。。。

  why??明明说n^3的啊?

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 410
  9 #define Maxm 160010
 10 // #define INF 0x7fffffff
 11 #define LL long long
 12 const LL INF=1LL<<62;
 13
 14 LL mymin(LL x,LL y) {return x<y?x:y;}
 15 LL mymax(LL x,LL y) {return x>y?x:y;}
 16
 17 int N;
 18
 19 int n,m;
 20 int match[Maxn],op[Maxn];
 21 LL eg[Maxn][Maxn],lx[Maxn],ly[Maxn],slack[Maxn];
 22 int visx[Maxn],visy[Maxn],pre[Maxn];
 23
 24 void mh(int y)
 25 {
 26     for(int x,z;y>0;y=z)
 27     {
 28         x=pre[y];z=op[x];
 29         op[x]=y;match[y]=x;
 30     }
 31 }
 32
 33 int nt;
 34 void ffind(int st)
 35 {
 36     for(int i=1;i<=N;i++) slack[i]=INF;
 37     queue<int> q;nt++;
 38     q.push(st);visx[st]=nt;
 39     while (1)
 40     {
 41         while(!q.empty())
 42         {
 43             int x=q.front();q.pop();
 44             for(int y=1;y<=N;y++)
 45              if(visy[y]!=nt)
 46              {
 47                  if(lx[x]+ly[y]==eg[x][y])
 48                  {
 49                      pre[y]=x;
 50                      if(!match[y]) {mh(y);return;}
 51                      q.push(match[y]);
 52                      visx[match[y]]=nt;visy[y]=nt;
 53                  }
 54                  else if(slack[y]>lx[x]+ly[y]-eg[x][y])
 55                     slack[y]=lx[x]+ly[y]-eg[x][y],pre[y]=x;
 56              }
 57         }
 58         LL delta=INF;
 59         for(int y=1;y<=N;y++) if(visy[y]!=nt) delta=mymin(delta,slack[y]);
 60         for(int i=1;i<=N;i++)
 61         {
 62             if(visx[i]==nt) lx[i]-=delta;
 63             if(visy[i]==nt) ly[i]+=delta;
 64             else slack[i]-=delta;
 65         }
 66         for(int i=1;i<=N;i++) if(visy[i]!=nt&&slack[i]==0)
 67         {
 68             if(!match[i]) {mh(i);return;}
 69             q.push(match[i]);
 70             visx[match[i]]=nt;visy[i]=nt;
 71         }
 72     }
 73 }
 74
 75
 76 LL KM()
 77 {
 78     memset(visx,0,sizeof(visx));
 79     memset(visy,0,sizeof(visy));
 80     for (int i=1;i<=N;i++) lx[i]=ly[i]=0,op[i]=match[i]=0;
 81     for (int i=1;i<=N;i++)
 82      for (int j=1;j<=N;j++)
 83       lx[i]=mymax(lx[i],eg[i][j]);
 84     for (int i=1;i<=N;i++) ffind(i);
 85 }
 86
 87 void output()
 88 {
 89     LL ans=0;
 90     for(int i=1;i<=N;i++) ans+=lx[i]+ly[i];
 91     printf("%lld\n",ans);
 92     for(int i=1;i<=n;i++) if(eg[i][op[i]]!=0) printf("%d ",op[i]);
 93     else printf("0 ");printf("\n");
 94 }
 95
 96 void init()
 97 {
 98     int l;
 99     memset(eg,0,sizeof(eg));
100     scanf("%d%d%d",&n,&m,&l);
101     for(int i=1;i<=l;i++)
102     {
103         int x,y;
104         LL c;
105         scanf("%d%d%lld",&x,&y,&c);
106         eg[x][y]=mymax(eg[x][y],c);
107     }
108     N=mymax(n,m);
109 }
110
111 int main()
112 {
113     init();
114         KM();
115     output();
116         return 0;
117 }

时间: 2024-10-09 21:11:33

【UOJ 80】 二分图最大权匹配的相关文章

uoj#80 二分图最大权匹配

题意:给定二分图,有边权,求最大边权匹配.边权非负. 解:KM算法求解最大权完备匹配. 完备匹配就是点数少的那一边每个点都有匹配. 为了让完备匹配与最大权匹配等价,我们添加若干条0边使之成为完全二分图(自造名词别在意......) 为了让左边成为点数较少的一边,我们还要添加一些虚点,m = max(n,m) 然后求解完备匹配. KM的DFS写法会被卡成n4,如果你不在意可以写......反正在uoj上会被卡爆. 模板就不放了,反正没啥用,放了还我 误 我 自 己. 过程就是一次为每个点寻找匹配.

UOJ#80 二分图最大权匹配 [模板题]

从前一个和谐的班级,有 nlnl 个是男生,有 nrnr 个是女生.编号分别为 1,…,nl1,…,nl 和 1,…,nr1,…,nr. 有若干个这样的条件:第 vv 个男生和第 uu 个女生愿意结为配偶,且结为配偶后幸福程度为 ww. 请问这个班级里幸福程度之和最大是多少? 输入格式 第一行三个正整数,nl,nr,mnl,nr,m. 接下来 mm 行,每行三个整数 v,u,wv,u,w 表示第 vv 个男生和第 uu 个女生愿意结为配偶,且幸福程度为 ww.保证 1≤v≤nl1≤v≤nl,1≤

二分图最大权匹配(KM算法)

#80. 二分图最大权匹配 统计 描述 提交 自定义测试 从前一个和谐的班级,有 $n_l$ 个是男生,有 $n_r$ 个是女生.编号分别为 $1, \dots, n_l$ 和 $1, \dots, n_r$. 有若干个这样的条件:第 $v$ 个男生和第 $u$ 个女生愿意结为配偶,且结为配偶后幸福程度为 $w$. 请问这个班级里幸福程度之和最大是多少? 输入格式 第一行三个正整数,$n_l, n_r, m$. 接下来 $m$ 行,每行三个整数 $v, u, w$ 表示第 $v$ 个男生和第 $

[hdu1533]二分图最大权匹配 || 最小费用最大流

题意:给一个n*m的地图,'m'表示人,'H'表示房子,求所有人都回到房子所走的距离之和的最小值(距离为曼哈顿距离). 思路:比较明显的二分图最大权匹配模型,将每个人向房子连一条边,边权为曼哈顿距离的相反数(由于是求最小,所以先取反后求最大,最后再取反回来即可),然后用KM算法跑一遍然后取反就是答案.还可以用最小费用最大流做,方法是:从源点向每个人连一条边,容量为1,费用为0,从每个房子向汇点连一条边,容量为1,费用为0,从每个人向每个房子连一条边,容量为1,费用为曼哈顿距离的值,建好图后跑一遍

[ACM] HDU 2255 奔小康赚大钱 (二分图最大权匹配,KM算法)

奔小康赚大钱 Problem Description 传说在遥远的地方有一个很富裕的村落,有一天,村长决定进行制度改革:又一次分配房子. 这但是一件大事,关系到人民的住房问题啊. 村里共同拥有n间房间,刚好有n家老百姓,考虑到每家都要有房住(假设有老百姓没房子住的话.easy引起不安定因素),每家必须分配到一间房子且仅仅能得到一间房子. 还有一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.因为老百姓都比較富裕,他们都能对每一间房子在他们的经济范围内出一定的价格,比方有3间房

HDU2255 奔小康赚大钱 —— 二分图最大权匹配

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11022    Accepted Submission(s): 4877 Problem Description 传说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行

POJ2195 Going Home[费用流|二分图最大权匹配]

Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22088   Accepted: 11155 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertica

ural 1076 Trash 二分图最大权匹配(费用流实现)

统计每种垃圾的总和,若将K种垃圾倒入第F个垃圾桶,那么花费就是K-F(k)  (自己已经有的垃圾不用倒). 然后就是简单的二分图建图. #include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define MAXN 1000 #define MAXM 1000000 #define INF 0x3f3f3f3f struct no

hdu 2255 二分图最大权匹配 *

题意:说在遥远的地方有一个非常富裕的村落,有一天,村长决定进行制度改革:重新分配房子.这可是一件大事,关系到人民的住房问题啊.村里共有n间房间,刚好有n家老百姓,考虑到每家都要有房住(如果有老百姓没房子住的话,容易引起不安定因素),每家必须分配到一间房子且只能得到一间房子.另 一方面,村长和另外的村领导希望得到最大的效益,这样村里的机构才会有钱.由于老百姓都比较富裕,他们都能对每一间房子在他们的经济范围内出一定的价格, 比如有3间房子,一家老百姓可以对第一间出10万,对第2间出2万,对第3间出2

BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]

传送门 题意: 给一张无向图和一棵生成树,改变一些边的权值使生成树为最小生成树,代价为改变权值和的绝对值,求最小代价 线性规划的形式: $Min\quad \sum\limits_{i=1}^{m} \delta_i$ $Sat\quad $非树边边权$\ge$生成树上路径任何一条边的边权 $i$非树边$j$树边 $w_i+\delta_i \ge w_j-\delta_j$ 然后可以转化成二分图最小顶标和来求解 这里需要求二分图最大权非完美匹配,我的做法是遇到$d[t] < 0$就退出,反正这