对偶图的应用

对偶图的应用

学习的博客
将平面图的最小割转化为对偶图,然后对对偶图求最短路,这条最短路对应着原图的一个最小割

推荐的题目
nowcoder
bzoj1001

1001题解

bzoj 1001

原来求的是平面图的最小割
但是图上面的点高达1e6,边高达3e6,因此网络流就凉了

我们可以将原图转化为对偶图,然后求对偶图的最短路,这条最短路就对应着原图的最小割。
这个还是相当的直观的

平面图的连边的关系需要好好的推导一下
样例的建图的序号,上面的是0号节点,下面的是2(n-1)(m-1)+1的终点
2\1 5\2 6\3
10\7 11\8 12\9

ac code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6+10;
const int inf = 1e9;
struct Node{
int v, next, w;
}node[maxn*3];
int minn = inf;
int N, M;
int tot, head[maxn];
int dist[maxn];
bool vis[maxn];
int cnt[maxn];
int end_pos;
void init(){
memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int w){
node[tot].v=v,node[tot].w=w,node[tot].next=head[u],head[u]=tot++;
node[tot].v=u,node[tot].w=w,node[tot].next=head[v],head[v]=tot++;
}
void build_graph(){
scanf("%d%d",&N,&M); end_pos=2*(N-1)*(M-1)+1;
int t;
if(N==1){
for(int i=1;i<M;++i){
scanf("%d",&t);
if(t<minn) minn=t;
}
return ;
}
else if(M==1){
for(int i=1;i<N;++i){
scanf("%d",&t);
if(t<minn) minn=t;
}
return ;
}
for(int i=1;i<=end_pos;++i) dist[i]=inf;
//横边
for(int i=1;i<=2*(N-1)+1;i+=2)
for(int j=1;j<M;++j){
scanf("%d",&t);
if(i==1) add_edge(j,0,t);
else if(i==2*(N-1)+1) add_edge(end_pos-(M-j),end_pos,t);
else add_edge((i-2)*(M-1)+j,(i-1)*(M-1)+j,t);
}
//纵边
for(int i=1;i<2*(N-1)+1;i+=2)
for(int j=1;j<=M;++j){
scanf("%d",&t);
if(j==1) add_edge(i*(M-1)+1,end_pos,t);
else if(j==M) add_edge(i*(M-1),0,t);
else add_edge(i*(M-1)+j,(i-1)*(M-1)+j-1,t);
}
//斜边
for(int i=1;i<2*(N-1)+1;i+=2)
for(int j=1;j<M;++j){
scanf("%d",&t);
add_edge((i-1)*(M-1)+j,i*(M-1)+j,t);
}
}
bool spfa(int s){
memset(cnt, 0, sizeof(cnt)), memset(vis, 0, sizeof(vis));
dist[s] = 0;
cnt[s] = 0, vis[s] = true;
queue<int> q;
while(!q.empty()) q.pop();
q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for(int i=head[u]; ~i; i=node[i].next){
int v=node[i].v;
if(dist[v]>dist[u]+node[i].w){
dist[v] = dist[u]+node[i].w;
if(!vis[v]){
cnt[v]++;
vis[v] = true;
q.push(v);
if(cnt[v]>2*(N-1)*(M-1)+2) return false;
}
}
}
}
return true;
}
int main(){
init();
build_graph();
if(minn == inf){
spfa(0);
// for(int i=0; i<=2*(N-1)*(M-1)+1; i++){
// cout<<i<<" "<<dist[i]<<endl;
// }
printf("%d\n", dist[end_pos]);
}
else printf("%d", minn);
return 0;
}

未解决的问题

文章目录
  1. 1. bzoj 1001
    1. 1.1. ac code
  2. 2. 未解决的问题
{{ live2d() }}