http://www.lydsy.com/JudgeOnline/problem.php?id=1001
题意:略
思路:开始我以为是个最小割,果断来了一发,毫无人性的TLE,最后看题解平面图的最小割可以转换成最短路径。
借别人一张图,很容易看懂。
只要找一条从 s 到 t 的最短路就是原图的最小割。
就是构图比较麻烦。。。。 我的代码中平面的编号是从 0 开始的,图中是从 1 开始的
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1000*1005;
struct Side{
int to, val, next;
};
int n, m;
int head[2*maxn];
Side side[6*maxn];
int dis[2*maxn];
bool vis[2*maxn];
void add(int a, int b, int val, int pos){
side[pos].to = b;
side[pos].val = val;
side[pos].next =head[a];
head[a] = pos;
}
int Spfa(int s, int t)
{
queue<int> que;
memset(dis, 63, sizeof(dis));
memset(vis, false, sizeof(vis));
dis[s] = 0;
que.push(s);
vis[s] = true;
while(!que.empty()){
int rt = que.front();
que.pop();
vis[rt] = false;
for(int i = head[rt]; ~i; i = side[i].next){
Side rw = side[i];
if(dis[rw.to] <= dis[rt] + rw.val)
continue;
dis[rw.to] = dis[rt] + rw.val;
if(!vis[rw.to]){
que.push(rw.to);
vis[rw.to] = true;
}
}
}
return dis[t];
}
int main()
{
while(~scanf("%d%d", &n, &m)){
int temp, top = 0, minn = inf;
int s = (n-1)*(m-1) << 1, t = s | 1;
memset(head, -1, sizeof(head));
for(int i = 0; i < n; i++){
for(int k = 0; k < m-1; k++){
scanf("%d", &temp);
minn = minn < temp ? minn : temp; //用于处理(m == 1 || n == 1)
if(i == 0){
add(s, k<<1, temp, top++); // s 到最上面的三角形
}
else if(i == n-1){
add(((i-1 )*(m-1)+k)<<1|1, t, temp, top++); //最下面的三角形到 t
}
else{
add(((i-1)*(m-1)+k)<<1|1, (i*(m-1)+k)<<1, temp, top++); //其他
add((i*(m-1)+k)<<1, ((i-1)*(m-1)+k)<<1|1, temp, top++);
}
}
}
for(int i = 0; i < n-1; i++){
for(int k = 0; k < m; k++){
scanf("%d", &temp);
minn = minn < temp ? minn : temp;
if(k == 0){
add((i*(m-1)+k)<<1|1, t, temp, top++); //最左边的三角形到 t
}
else if(k == m-1){
add(s, (i*(m-1)+k-1)<<1, temp, top++); // s 到最右边的三角形
}
else{
add((i*(m-1)+k-1)<<1, (i*(m-1)+k)<<1|1, temp, top++); // 其他
add((i*(m-1)+k)<<1|1, (i*(m-1)+k-1)<<1, temp, top++);
}
}
}
for(int i = 0; i < n-1; i++){
for(int k = 0; k < m-1; k++){
scanf("%d", &temp);
minn = minn < temp ? minn : temp;
add((i*(m-1)+k)<<1, (i*(m-1)+k)<<1|1, temp, top++); //斜的
add((i*(m-1)+k)<<1|1, (i*(m-1)+k)<<1, temp, top++);
}
}
if(m <= 1 && n <= 1)
printf("0\n");
else if(m == 1 || n == 1)
printf("%d\n", minn);
else
printf("%d\n", Spfa(s, t));
}
return 0;
}