/*刚开始不会写,最大点权独立集神马都不知道,在潘神的指导下终于做出来,灰常感谢ps;
和方格取数差不多奇偶建图,对于D必割点权为0,对于.必然不割点权为inf。然后和方格取数差不多的建图
.--.||E权值为2,,.||E--D权值为0.
最大点权独立集=sum-最小点权覆盖。
*/
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define inf 0x3fffffff
#define ii 50
#define N 3000
struct node {
int u,v,w,next;
}bian[N*6];
int head[N],yong,s,t,dis[N];
void init(){
yong=0;
memset(head,-1,sizeof(head));
memset(dis,-1,sizeof(dis));
}
void addedge(int u,int v,int w) {
bian[yong].u=u;
bian[yong].v=v;
bian[yong].w=w;
bian[yong].next=head[u];
head[u]=yong++;
}
void add(int u,int v,int w) {
addedge(u,v,w);
addedge(v,u,0);
}
void bfs() {
int u,v,i;
queue<int>q;
q.push(t);
dis[t]=0;
while(!q.empty()) {
u=q.front();
q.pop();
for(i=head[u];i!=-1;i=bian[i].next) {
v=bian[i].v;
if(dis[v]==-1) {
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return ;
}
int ISAP() {
int sum=0;
bfs();
int gap[N],cur[N],stac[N],top,i;
memset(gap,0,sizeof(gap));
for(i=s;i<=t;i++) {
gap[dis[i]]++;
cur[i]=head[i];
}
int k=s;
top=0;
while(dis[s]<t+1) {
if(k==t) {
int minn=inf,index;
for(i=0;i<top;i++) {
int e=stac[i];
if(minn>bian[e].w) {
minn=bian[e].w;
index=i;
}
}
for(i=0;i<top;i++) {
int e=stac[i];
bian[e].w-=minn;
bian[e^1].w+=minn;
}
sum+=minn;
top=index;
k=bian[stac[top]].u;
}
for(i=cur[k];i!=-1;i=bian[i].next) {
int v=bian[i].v;
if(bian[i].w&&dis[k]==dis[v]+1) {
cur[k]=i;
k=v;
stac[top++]=i;
break;
}
}
if(i==-1) {
int m=t+1;
for(i=head[k];i!=-1;i=bian[i].next)
if(m>dis[bian[i].v]&&bian[i].w) {
m=dis[bian[i].v];
cur[k]=i;
}
if(--gap[dis[k]]==0)break;
gap[dis[k]=m+1]++;
if(k!=s)
k=bian[stac[--top]].u;
}
}
return sum;
}
int main() {
int n,m,i,j,T,id[ii][ii],cnt,sum,f=0;
char ss[ii][ii];
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
cnt=1;sum=0;
init();
for(i=1;i<=n;i++) {
scanf("%s",ss[i]+1);
for(j=1;j<=m;j++) {
if(ss[i][j]=='.'||ss[i][j]=='E')//记录总数
sum+=4;
id[i][j]=cnt++;
}
}
s=0;t=n*m+1;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++) {
if((i+j)&1) {//奇偶建图与源点相连
if(ss[i][j]=='.')
add(s,id[i][j],inf);//必然不割
if(ss[i][j]=='D')//必割
add(s,id[i][j],0);
if(ss[i][j]=='E')//任意选择
add(s,id[i][j],4);
if(i>=2) {
if(ss[i][j]=='.'||ss[i][j]=='E') {
if(ss[i-1][j]=='.'||ss[i-1][j]=='E')add(id[i][j],id[i-1][j],2);//
if(ss[i-1][j]=='D')add(id[i][j],id[i-1][j],0);//
}
else
add(id[i][j],id[i-1][j],0);
}
if(j>=2) {
if(ss[i][j]=='.'||ss[i][j]=='E') {
if(ss[i][j-1]=='.'||ss[i][j-1]=='E')add(id[i][j],id[i][j-1],2);
if(ss[i][j-1]=='D')add(id[i][j],id[i][j-1],0);
}
else
add(id[i][j],id[i][j-1],0);
}
if(i<=n-1){
if(ss[i][j]=='.'||ss[i][j]=='E') {
if(ss[i+1][j]=='.'||ss[i+1][j]=='E')add(id[i][j],id[i+1][j],2);
if(ss[i+1][j]=='D')add(id[i][j],id[i+1][j],0);
}
else
add(id[i][j],id[i+1][j],0);
}
if(j<=m-1) {
if(ss[i][j]=='.'||ss[i][j]=='E') {
if(ss[i][j+1]=='.'||ss[i][j+1]=='E')add(id[i][j],id[i][j+1],2);
if(ss[i][j+1]=='D')add(id[i][j],id[i][j+1],0);
}
else
add(id[i][j],id[i][j+1],0);
}
}
else {//与汇点相连
if(ss[i][j]=='.')
add(id[i][j],t,inf);
if(ss[i][j]=='E')
add(id[i][j],t,4);
if(ss[i][j]=='D')
add(id[i][j],t,0);
}
}
printf("Case %d: ",++f);
printf("%d\n",sum-ISAP());
}
return 0;
}

hdu 4859 最大点权独立集的变形(方格取数的变形)的更多相关文章

  1. hdu 3657 最大点权独立集变形(方格取数的变形最小割,对于最小割建图很好的题)

    转载:http://blog.csdn.net/cold__v__moon/article/details/7924269 /* 这道题和方格取数2相似,是在方格取数2的基础上的变形. 方格取数2解法 ...

  2. HDU 1565 最大点权独立集

    首先要明白图论的几个定义: 点覆盖.最小点覆盖: 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是“点” 覆盖了所有“边”.. 最小点覆盖(minimum vertex covering ...

  3. hdu 1565&&hdu 1569 (最大点权独立集)

    题目意思很明确就是选一些没有相连的数字,使和最大,建成二分图后求最大点权独立集,, #include<stdio.h> #include<string.h> const int ...

  4. hdu 3657最大点权独立集变形(方格取数变形)

    /* 分奇偶为二部图,s与奇建图,t与偶建图,权值为当前数的值,如果遇到必取的权值置为inf. 奇偶建边为相邻的权值为2*(x&y):所有数的值-最小点全覆盖. 置为inf意为不能割掉.奇偶边 ...

  5. [学习笔记]最小割之最小点权覆盖&&最大点权独立集

    最小点权覆盖 给出一个二分图,每个点有一个非负点权 要求选出一些点构成一个覆盖,问点权最小是多少 建模: S到左部点,容量为点权 右部点到T,容量为点权 左部点到右部点的边,容量inf 求最小割即可. ...

  6. HDU 1565 方格取数(1) 轮廓线dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others) ...

  7. HDU-1565 方格取数(1)

    http://acm.hdu.edu.cn/showproblem.php?pid=1565 方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Me ...

  8. HDU 1569 - 方格取数(2) - [最大点权独立集与最小点权覆盖集]

    嗯,这是关于最大点权独立集与最小点权覆盖集的姿势,很简单对吧,然后开始看题. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1569 Time Limi ...

  9. HDU 1565 1569 方格取数(最大点权独立集)

    HDU 1565 1569 方格取数(最大点权独立集) 题目链接 题意:中文题 思路:最大点权独立集 = 总权值 - 最小割 = 总权值 - 最大流 那么原图周围不能连边,那么就能够分成黑白棋盘.源点 ...

随机推荐

  1. 为什么要使用XHTML?

    XHTML 是什么? XHTML 指可扩展超文本标签语言(EXtensible HyperText Markup Language). XHTML 的目标是取代 HTML. XHTML 与 HTML ...

  2. vue实现全选,反选

    1.example.vue <template> <table class="table-common"> <tr> <th class= ...

  3. 如何使js函数异步执行

    CallbacksCallbacks使用场景在哪里?在很多时候需要控制一系列的函数顺序执行.那么一般就需要一个队列函数来处理这个问题: function Aaron(List, callback) { ...

  4. 零基础如何学习Java和web前端

    今天说一下零基础到底能不能学习Java,为什么有的人说学不了呢,那么接下来我为大家揭晓,零基础到底适合不适合学习Java. 零基础学习Java的途径第一个就是看视频,然后就是看书,或者在线下报个培训班 ...

  5. vue tab 点击请求方法

    页面: <Tabs value="name1" style="width: 100%;height: 900px;" @on-click="ge ...

  6. 分享一些对IT人员非常好用的资源

    前言 分享一下本人工作至今整理的一些好用的资源,这些资源主要是一些工作和生活中用到的文档.软件和网站. 文档主要是面试相关的文档和技术文档,其中面试文档主要是Java这块的,技术文档就有很多,除了Ja ...

  7. Vue电商SKU组合算法问题

    前段时间,公司要做“添加商品”业务模块,这也算是电商业务里面的一个难点了. 令我印象最深的不是什么“组合商品”.“关联商品”.“关联单品”,而是商品SKU的组合问题. 这个问题特别有意思,当时虽然大体 ...

  8. 关于网页的自适应问题一---Media Query(媒介查询)

    1.Media Query(媒介查询) 通过不同的媒介类型和条件定义样式表规则.媒介查询让CSS可以更精确作用于不同的媒介类型和同一媒介的不同条件.媒介查询的大部分媒介特性都接受min和max用于表达 ...

  9. JAVA小记(一)

    java中向上转型.向下转型.内部类中所需注意的问题: 向上转型与向下转型: 举个例子:有2个类,Father是父类,Son类继承自Father. Father f1 = new Son();   / ...

  10. python中set元素为可迭代元素相加

    #a 与 b必须是两个相同类型的可迭代对象 a = "1" b = "2" print(set(a + b))  # {'1', '2'} a = " ...