题意:

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

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

  原题:

  小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. 2 配置Ionic开发环境以及创建新的项目

    1.开发环境需要的软件有: node.js http://nodejs.org  可以到官方网站下载对应平台的安装包安装即可,如果已经安装,需要把它升级到最新的稳定版本   在终端可以输入$node ...

  2. 三、jQuery--jQuery基础--jQuery基础课程--第1章 初识jQuery

    环境搭建 搭建一个jQuery的开发环境非常方便,可以通过下列几个步骤进行. 下载jQuery文件库 在jQuery的官方网站(http://jquery.com)中,下载最新版本的jQuery文件库 ...

  3. 登录到mysql查看binlog日志

    查看当前第一个binlog文件的内容 show binlog events; 查看指定binlog文件内容 show binlog events in 'mysql-bin.000002'; 查看当前 ...

  4. Unity依赖注入使用

    构造器注入(Constructor Injection):IoC容器会智能地选择选择和调用适合的构造函数以创建依赖的对象.如果被选择的构造函数具有相应的参数,IoC容器在调用构造函数之前会自定义创建相 ...

  5. acpi参考网站

    1.acpi官网: http://www.acpi.info/

  6. 攻城狮在路上(肆)How tomcat works(零) 前言说明

    最近几篇是关于How tomcat works一书的读书笔记. 通过数个章节逐渐实现一个tomcat的功能. 源码下载地址:http://zhidao.baidu.com/share/7007af0f ...

  7. 攻城狮在路上(贰) Spring(三)--- Spring 资源访问利器Resource接口

    Spring为了更好的满足各种底层资源的访问需求.设计了一个Resource接口,提供了更强的访问底层资源的能力.Spring框架使用Resource装载各种资源,包括配置文件资源.国际化属性文件资源 ...

  8. OGG异常处理

    ALTER REPLICAT LCMA1REP,BEGIN NOW 从最新的trail文件开始读取 ALTER REPLICAT LCMA1REP,EXTSEQNO 191(对应的 trail的序号 ...

  9. hdu 4038 2011成都赛区网络赛H 贪心 ***

    贪心策略 1.使负数为偶数个,然后负数就不用管了 2.0变为1 3.1变为2 4.2变为3 5.若此时操作数剩1,则3+1,否则填个1+1,然后回到5

  10. 配置ogg异构oracle-mysql(1)基础环境配置

    一.环境描述: 192.168.0.164 ( Oracle ) —> 192.168.0.165 (Mysql ) 版本: 操作系统:redhat5.8 Oracle:  11.2.0.3 M ...