题意:

  给一张二分图,每个点与两个特定点又一条边相连,边权非负,让你给这个二分图每个点一个顶标,让每一条边两端顶标和大于等于这条边。求出最小顶标和。

  这当然是翻译过的题目。。。

  原题:

  小Y和小P无聊的时候就喜欢玩游戏,但是每次小P都输给了小Y。终于有一天,你看不过去了,决定帮小P一把。
游戏是这样的,一个N*M的棋盘(保证n或m中,至少有一个为偶数)。相邻格子之间有一个给定的正整数权值。要你给这些格子填上一些值,使得相邻两个格子本身的权值之和,要大于等于他们之间给定的权值。并且要使得所有格子权值之和最小。

  不过也挺显然的。。。当然在你学完KM后对这种思想还是非常敏感。。如果没学过会怎么乱搞呢?。。。因确斯汀。

SOL:

  还有题解?。。。这不就跑个KM顶标什么的都出来了。。。数据较大用个领接表。。也就复习一下KM

CODE:

  

/*==========================================================================
# Last modified: 2016-03-04 09:11
# Filename: t2.cpp
# Description:
==========================================================================*/
#define me AcrossTheSky
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> #include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector> #define lowbit(x) (x)&(-x)
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define getlc(a) ch[(a)][0]
#define getrc(a) ch[(a)][1] #define maxn 11050
#define maxm 50000
#define pi 3.1415926535898
#define _e 2.718281828459
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull; template<class T> inline
void read(T& num) {
bool start=false,neg=false;
char c;
num=0;
while((c=getchar())!=EOF) {
if(c=='-') start=neg=true;
else if(c>='0' && c<='9') {
start=true;
num=num*10+c-'0';
} else if(start) break;
}
if(neg) num=-num;
}
/*==================split line==================*/
struct Edge{
int to,len;
}e[maxm];
int s[maxn],t[maxn],slack[maxn],lx[maxn],ly[maxn];
bool color[maxn],S[maxn],T[maxn],vis[maxn];
int out[5050][5050],link[maxn],ord[maxn],first[maxn],next[maxm];
int sumt=0,sums=0,sume=0;
int n,m;
void addedge(int x,int y,int l){
sume++; e[sume].to=y; e[sume].len=l;
next[sume]=first[x]; first[x]=sume;
}
void updata(){
int a=INF;
FORP(j,1,sumt) if (!T[j]) a=min(a,slack[j]);
FORP(i,1,sums) if (S[i]) lx[i]-=a;
FORP(i,1,sumt) if (T[i]) ly[i]+=a;
else slack[i]-=a;
return;
}
bool match(int x){
S[x]=true;
//FORP(i,1,sumt){
for (int p=first[s[x]]; p!=-1; p=next[p]){
int i=ord[e[p].to];
if (T[i]) continue;
if (lx[x]+ly[i]==e[p].len){//way[s[x]][t[i]]){
T[i]=true;
if (!link[i] || match(link[i])){
link[i]=x;
return true;
}
}
else slack[i]=min(slack[i],lx[x]+ly[i]-e[p].len);//way[s[x]][t[i]]);
}
return false;
}
void KM(){
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(link,0,sizeof(link));
FORP(i,1,sums)
for (int j=first[s[i]];j!=-1;j=next[j])
lx[i]=max(lx[i],e[j].len);
//FORP(j,1,sumt) lx[i]=max(lx[i],way[s[i]][t[j]]); FORP(i,1,sums){
FORP(j,1,sumt) slack[j]=INF;
while (1){
memset(S,false,sizeof(S));
memset(T,false,sizeof(T));
if (match(i)) break;
else updata();
}
}
}
void get(int node,int v){
int x=node/m+1,y=node%m;
if (y==0) y=m,x--;
out[x][y]=v;
}
void paint(int x,int y,bool fa){
int node=(x-1)*m+y;
if (vis[node]) return;
vis[node]=true;
color[node]=!fa;
if (color[node]) s[++sums]=node,ord[node]=sums;
else t[++sumt]=node,ord[node]=sumt;
if (y==0) y=m,x--;
if (x<n) paint(x+1,y,color[node]);
if (y<m) paint(x,y+1,color[node]);
}
int main(){
read(n); read(m);
memset(first,-1,sizeof(first));
FORP(i,1,n){
FORP(j,1,2*m) {
int x; read(x);
if (j>2*(m-1)+1 || (i==n && j%2==1)) continue;
if (j%2==1) {
int node1=(i-1)*m+j/2+1;
int node2=node1+m;
addedge(node1,node2,x);
addedge(node2,node1,x);
}
else {
int node1=(i-1)*m+j/2;
int node2=node1+1;
addedge(node2,node1,x);
addedge(node1,node2,x);
}
}
}
memset(vis,false,sizeof(vis));
paint(1,1,false); KM();
int ans=0;
FORP(i,1,sums) {ans+=lx[i]; get(s[i],lx[i]);}
FORP(i,1,sumt) {ans+=ly[i]; get(t[i],ly[i]);}
printf("%d\n",ans);
FORP(i,1,n){
FORP(j,1,m) printf("%d ",out[i][j]);
cout << endl;
}
}

争夺 & KM思想的更多相关文章

  1. POJ 3686 & 拆点&KM

    题意: 有n个订单,m个工厂,第i个订单在第j个工厂生产的时间为t[i][j],一个工厂可以生产多个订单,但一次只能生产一个订单,也就是说如果先生产a订单,那么b订单要等到a生产完以后再生产,问n个订 ...

  2. 二分图 最大权匹配 km算法

    这个算法的本质还是不断的找增广路: KM算法的正确性基于以下定理:若由二分图中所有满足A[i]+B[j]=w[i,j]的边(i,j)构成的子图(称做相等子图)有完备匹配,那么这个完备匹配就是二分图的最 ...

  3. 【HDU 2255】奔小康赚大钱 (最佳二分匹配KM算法)

    奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  4. KM算法专题

    原文:http://972169909-qq-com.iteye.com/blog/1184514 题目地址:这里. 1)求图中所有环的总长度(环的长度不唯一)的最小值.当无法得到完备匹配时说明环不存 ...

  5. HDU 2255 奔小康赚大钱 KM算法的简单解释

    KM算法一般用来寻找二分图的最优匹配. 步骤: 1.初始化可行标杆 2.对新加入的点用匈牙利算法进行判断 3.若无法加入新编,修改可行标杆 4.重复2.3操作直到找到相等子图的完全匹配. 各步骤简述: ...

  6. 二分图匹配之最佳匹配——KM算法

    今天也大致学了下KM算法,用于求二分图匹配的最佳匹配. 何为最佳?我们能用匈牙利算法对二分图进行最大匹配,但匹配的方式不唯一,如果我们假设每条边有权值,那么一定会存在一个最大权值的匹配情况,但对于KM ...

  7. 【原创】我的KM算法详解

    0.二分图 二分图的概念 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V, E)是一个无向图.如果顶点集V可分割为两个互不相交的子集X和Y,并且图中每条边连接的两个顶点一个在X中,另一个在Y ...

  8. KM算法及其应用

    在二分图匹配中有最大匹配问题,使用匈牙利算法或者网络流相关算法解决,如果给每条边增加一个权值,求权值和最大的匹配方案就叫做最大权匹配问题.其实之前所说的最大匹配就是权值为1的最大权匹配. 求最大权完备 ...

  9. (转)二分图匹配匈牙利算法与KM算法

    匈牙利算法转自于: https://blog.csdn.net/dark_scope/article/details/8880547 匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名 ...

随机推荐

  1. React Native实例之房产搜索APP

    React Native 开发越来越火了,web app也是未来的潮流, 现在react native已经可以完成一些最基本的功能. 通过开发一些简单的应用, 可以更加熟练的掌握 RN 的知识. 在学 ...

  2. mysql 三个表连接查询

    权限表(permission)10 字段名称 类型 约束 描述 authorityid integer Pk not null 权限流水号id    PK userNameId int not nul ...

  3. (1)第一个ASP.NET Web API

      Install-Package Microsoft.AspNet.WebApi . Global.asax protected void Application_Start() { AreaReg ...

  4. eclipse项目迁移到android studio(图文最新版)

    前言 最近Android studio(下文简称AS)官方发布了正式版,目前火得不行.个人认为主要是因为android是google自家的产品,AS也是他自己搞的IDE,以后的趋势android开发肯 ...

  5. ODATA WEB API(二)----ODATA服务与客户端

    一.概述 ODATA不经可以作为WebAPI建立相应的WEBAPI控制器,还可以建立ODataControl控制器,能够通过插件建立第三方ODataClinet类库:调用和使用数据变得简单可行. 二. ...

  6. PHP不同域名cookie共享(单点登录实现原理)

    PHP使用P3P完成COOKIE跨域操作实际实用中,类似的需求有,比如说我们有两个域名,我们想实现在一个域名登录后,能自动完成另一个域名的登录,也就是单点登录(SSO)功能.为了测试的方便,先编辑ho ...

  7. python调用系统命令popen、system

    python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容.所以说一般我们认为popen ...

  8. 为GDI函数增加透明度处理

    用户对客户端的UI的要求越来越高,采用alpha通道对前景背景做混合是提高UI质量的重要手段. UI开发离不开GDI,然后要用传统的GDI函数来处理alpha通道通常是一个恶梦:虽然有AlphaBle ...

  9. [荐]SWFObject 2最新版语法调用示例

    我一直都在用SWFObject 插入flash,好处多多,代码简洁,不会出现微软的“单击此处以激活控件”的提示(据可靠消息,这个是微软惹的官司,其结果是害苦了用户).不过先前的 调用方法着实有些繁琐, ...

  10. MSComm32控件注册方法

    两种方法去解决,一种方法是当我们安装VC++6.0/VB6.0时,如果选择了ACtiveX控件项(自定义安装),MSComm控件就会自动安装在计算机上了,并在系统文件夹下多了3个文件:Mscomm.s ...