题意:

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

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

  原题:

  小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.2 顺序容器-list

    list(双向链表) 1) *  :包含头文件list **:不支持随机存取:增删元素时间是常数,只需要修改指针 2)成员函数 *  :vector的成员函数list基本都有 **:以下是部分独有成员 ...

  2. 【Jquery】【控件】flexigrid 自定义查询

    最近用flexigrid作报表,需要自定义条件进行查询,界面如下: 翻了半天文档也没找到如何用POST方法自行传递参数进行查询. 找了一个台湾人写的博客,却要改flexigrid的源代码,更不靠谱. ...

  3. Delphi管理多线程之线程局部存储:threadvar

    尽管多线程能够解决许多问题,但是同时它又给我们带来了很多的问题.其中主要的问题就是:对全局变量或句柄这样的全局资源如何访问?另外,当必须确保一个线程中的某些事件要在另一个线程中的其他时间之前(或之后) ...

  4. 【mysql中myisam和innodb的区别】

    单击进入源网页 要点摘要: 1.查看mysql存储引擎的状态mysql> show engines; 2.查看mysql默认的存储引擎mysql> show variables like ...

  5. poj 1007:DNA Sorting(水题,字符串逆序数排序)

    DNA Sorting Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 80832   Accepted: 32533 Des ...

  6. scala的tcp通信

    client: object ActorClient extends App { import actors.Actor, actors.remote.Node, actors.remote.Remo ...

  7. android 面试题

    一,什么是OOM (1)先从定义开始:Android(Java)中常见的容易引起内存泄漏的不良代码Android主要应用在嵌入式设备当中,而嵌入式设备由于一些众所周知的条件限制,通常都不会有很高的配置 ...

  8. SOA 架构中的ESB是更好的应用于异构系统集成整合还是用于统一服务调用/基础服务实施

    一.讨论主题与观点 写一篇文章.发现一次自觉得有意思的SOA架构方面的讨论,源于昨天AgileEAS.NET SOA 平台群(113723486)里几个群友的一次关于ESB的一次讨论. 大家的讨论观点 ...

  9. Objective-C编码规范:26个方面解决iOS开发问题(转)

    链接

  10. Android图像处理实例教程

    Android图像处理实例教程 原始出处 http://vaero.blog.51cto.com/4350852/856750