hdu 3807【最大最小定理】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3870

这道题是一道裸的求割问题也即求最大流,但是使用一般网络流这道

题会超时,这是这道题的难点,但是鉴于这道题的图的特殊性,可以

用最大最小定理来求割,这边是这道题的考察点。

推荐诸君看一下最大最小个定理,推荐链接:

http://www.doc88.com/p-386772667290.html

献上代码:

#include<stdio.h>

#include<string.h>

#include<algorithm>

#include<iostream>

#include<queue>

using namespace std;

const int maxh=700+10;

const int inf=1000000000;

typedef struct Edge

{

int to,next,w;

};

Edge E[2500000];

int head[500000],dis[500000],visit[500000],cnt,map[maxh][maxh];

void init()

{

memset(head,-1,sizeof(head));

cnt=0;

}

void add(int a,int b,int c)

{

E[cnt].to=b;

E[cnt].w=c;

E[cnt].next=head[a];

head[a]=cnt++;

E[cnt].to=a;

E[cnt].w=c;

E[cnt].next=head[b];

head[b]=cnt++;

}

void spfa(int s,int t)

{

for(int i=0;i<=t+10;i++)

{

dis[i]=inf;

visit[i]=0;

}

dis[s]=0;

queue<int>Q;

visit[s]=1;

Q.push(s);

while(!Q.empty())

{

int k=Q.front();

Q.pop();

visit[k]=0;

for(int i=head[k];i+1;i=E[i].next)

{

int to=E[i].to;

int w=E[i].w;

if(dis[k]+w<dis[to])

{

dis[to]=dis[k]+w;

if(visit[to])

continue;

visit[to]=1;

Q.push(to);

}

}

}

}

int main()

{

int T,n;

scanf("%d",&T);

while(T--)

{

scanf("%d",&n);

init();

for(int i=1;i<=n;i++)

for(int j=1;j<=n;j++)

scanf("%d",&map[i][j]);

int s=0,t=n*n+1;

for(int i=1;i<=n-1;i++)

{

add(s,i,map[1][i]);

add(s,i*(n-1),map[i][n]);

add((i-1)*(n-1)+1,t,map[i][1]);

add((n-2)*(n-1)+i,t,map[n][i]);

}

for(int i=1;i<=n-1;i++)

for(int j=1;j<=n-1;j++)

{

if(j+1<=n-1){

add((i-1)*(n-1)+j,(i-1)*(n-1)+j+1,map[i][j+1]);

}

if(i+1<=n-1){

add((i-1)*(n-1)+j,i*(n-1)+j,map[i+1][j]);

}

}

spfa(s,t);

printf("%d\n",dis[t]);

}

return 0;

}

时间: 2024-08-07 17:02:00

hdu 3807【最大最小定理】的相关文章

HDU 4862 Jump 最小k路径覆盖 费用流

gg... 题意: 给定n*m的矩阵 选<=k个起点 每个起点可以向右或向下跳任意步 花费是2点间的曼哈顿距离 若2个格子的数字一样 则赚取格子上的数字的价值 问:遍历整个图的最小花费 若不能遍历则输出-1 #include <stdio.h> #include <string.h> #include <iostream> #include <math.h> #include <queue> #include <set> #in

hdu 4966 GGS-DDU (最小树形图)

比较好的讲解:http://blog.csdn.net/wsniyufang/article/details/6747392 view code//首先为除根之外的每个点选定一条入边,这条入边一定要是所有入边中最小的. //现在所有的最小 入边都选择出来了,如果这个入边集不存在有向环的话,我们 //可以证明这个集合就是该图的最小树形图.这个证明并不是很难.如果存在有向 //环的话,我们就要将这 个有向环所称一个人工顶点,同时改变图中边的权.假 //设某点u在该环上,并设这个环中指向u的边权是in

HDU 4862 JUMP 最小费用最大流

2014 多校的B题,由于我不怎么搞图论,当时碰到这个题目,我怎么想都没往网络流方面弄,不过网络流真的是个好东西,对于状态多变,无法用动规或者数据结构来很好表示的时候,非常有用 这个题目要求每个点一定要访问到,并且每次访问的是没访问过的点,跳跃的方向为向右或者向下. 建图的时候,分成二分图,从一个超级源点向x部分建cap为1 cost为0的点,对所以可到达的点从x到y建cap为1,cost根据题目算出来,不过要算负值,因为我们要求得实际是最大费用,最后对结果求相反数即可.所有y部分的点对超级汇点

HDU 4966 GGS-DDU 最小树形图

题意: 给定n个技能,m个限制 下面是每个技能满级的级数 开始每个技能都是0级. m个限制 (c,l1) (d,l2) cost 若c技能已经>=l1级,那么把点亮d技能 从0级一路点到l2级的花费是cost ..他说的好有道理,我竟无言以对 _(:зゝ∠)_ 最小树形图,用0做根,触发每个技能的0级花费是0 若已经点亮技能的x级,则点亮该技能的x-1级花费就是0 #include <stdio.h> #include <string.h> #include <iost

HDU 3360-National Treasures(最小点覆盖+奇偶匹配)

/******************************************************* 题意: 现在有一个n*m的博物馆g,每一个g[i][j]要不是一个<=2^12 的数,要不就是-1. 如果这个点是-1,表示这个点有一个守卫 否则就是以g[i][j]为关键字规则的宝物. 具体规则是: 现在有12个被编号的点(题目中给出了图片),然后把g[i][j]表示成一个12位二进制数 ,从低位到高位(右到左)依次为1~12,如果某位i上是1,就表示在编号 为i的相对位置放置一个

hdu String Problem(最小表示法入门题)

hdu 3374 String Problem 最小表示法 view code#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> using namespace std; const int N = 10010; int n; char s[105]; map<

hdu 4494 Teamwork 最小费用最大流

Teamwork Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4494 Description Some locations in city A has been destroyed in the fierce battle. So the government decides to send some workers to repair these location

HDU 4859 海岸线 最小割

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4859 题解: 这题考察的是最小割. 我们可以这样想:海岸线的长短变化都是E引起的,我们通过把’E'变成'.'或'D'来使海岸线最大化. 我们要算海岸线就是算格子‘.'和格子'D'(在原有地图周围四面都要加’D‘)相邻的面数,要使它最大,就是要使'.'与’.':'D'与'D'相邻的面数最小,而面数最小可以用最小割来做. 现在我们先把格子上的点黑白染色,(i+j)%2==1的为A类,为0的为B类, 在

POJ 2195 Going Home / HDU 1533(最小费用最大流模板)

题目大意: 有一个最大是100 * 100 的网格图,上面有 s 个 房子和人,人每移动一个格子花费1的代价,求最小代价让所有的人都进入一个房子.每个房子只能进入一个人. 算法讨论: 注意是KM 和 MCMF算法,我写的是MCMF算法,一开始想的是连10000个点,但是不会连那些大众点之间的边,只会连超级点和普通点之间的边.后来觉得只要连房子点和 人点就可以了.连从人到房子的边,容量是1,花费是他们之间的曼哈顿距离,然后超级源点和超级汇点像上面那样连接,注意连点的时候把他们每个点都具体化一下,就