这道题目的题解在网上还是比较多的。首先先在这里整理一些平面图性质:
1) 平面图最小割等于对偶图s-t的最短路
2)平面图的生成树个数等于对偶图生成树的个数(不过好像1002的对偶图的Kirchoff矩阵=原图Kirchoff矩阵?)
反正这一题第一条就足够了。
那么怎么确定s和t在哪里?s就是填上s和t的边后产生的附加面,而t就是无界面。
想到这样,就开始写了。不过添加边的过程比较复杂,最好手推一下公式。为了方便,我设计了一个CShortestSolver的类。这样就很清晰了。
不多说,上代码:
#include <iostream>
#include <queue>
#include <cstdlib>
#include <cstring>
using namespace std;
const int maxm = 2500000;
//max node
const int maxn = 7000000;
//max size
struct edge
{
int to;
int next;
int w;
};
struct node
{
int d;
int id;
friend bool operator<(node a,node b)
{
return (a.d>b.d);
}
};
class CShortestSolver
{
private:
int head[maxm];
edge e[maxn];
int cur;
priority_queue<node> q;
bool vis[maxm];
private:
void init(int source,int size);
public:
CShortestSolver();
void addEdge(int from,int to,int weight);
int solve(int source,int size,int des);
};
CShortestSolver solver;
CShortestSolver::CShortestSolver()
{
memset(head,-1,sizeof head);
cur = 0;
};
void CShortestSolver::addEdge(int from,int to,int weight)
{
//cout << "Zulagen fra" << from << "fo" << to << endl;
e[cur].next = head[from];
e[cur].to = to;
e[cur].w = weight;
head[from] = cur;
cur++;
};
void CShortestSolver::init(int source,int size)
{
memset(vis,false,sizeof(vis));
node temp;
for (int i = 1;i <= size;++i)
{
if (i != source)
{
temp.d = 2147483647;
temp.id = i;
q.push(temp);
}
else
{
temp.d = 0;
temp.id = i;
q.push(temp);
}
}
}
int CShortestSolver::solve(int source,int size,int des)
{
init(source,size);
node temp;
int cnt = 1;
while (cnt <= size)
{
node top = q.top();
q.pop();
if (vis[top.id]) continue;
cnt++;
if (top.id == des) return top.d;
vis[top.id] = true;
int cur = head[top.id];
while (cur != -1)
{
temp.id = e[cur].to;
temp.d = top.d + e[cur].w;
q.push(temp);
cur = e[cur].next;
}
}
return -1;
}
int main(int argc,char * argv[])
{
int n,m;
cin >> n >> m;
for (int i = 1;i <= n;++i)
{
for (int j = 1;j <= m-1;++j)
{
int w;
cin >> w;
if (i == 1)
{
solver.addEdge(2*j,2*(n-1)*(m-1)+1,w);
solver.addEdge(2*(n-1)*(m-1)+1,2*j,w);
}
else if (i == n)
{
solver.addEdge(2*(n-2)*(m-1)+2*(j-1)+1,2*(n-1)*(m-1)+2,w);
solver.addEdge(2*(n-1)*(m-1)+2,2*(n-2)*(m-1)+2*(j-1)+1,w);
}
else
{
solver.addEdge(2*(m-1)*(i-2)+2*(j-1)+1,2*(m-1)*(i-1)+2*(j-1)+2,w);
solver.addEdge(2*(m-1)*(i-1)+2*(j-1)+2,2*(m-1)*(i-2)+2*(j-1)+1,w);
}
}
}
for (int i = 1;i <= n-1;++i)
{
for (int j = 1;j <= m;++j)
{
int w;
cin >> w;
if (j == 1)
{
solver.addEdge(2*(n-1)*(m-1)+2,2*(m-1)*(i-1)+1,w);
solver.addEdge(2*(m-1)*(i-1)+1,2*(n-1)*(m-1)+2,w);
}
else if (j == m)
{
solver.addEdge(2*(m-1)*(i-1)+2*j-2,2*(n-1)*(m-1)+1,w);
solver.addEdge(2*(n-1)*(m-1)+1,2*(m-1)*(i-1)+2*j-2,w);
}
else
{
solver.addEdge(2*(m-1)*(i-1)+2*(j-1),2*(m-1)*(i-1)+2*j-1,w);
solver.addEdge(2*(m-1)*(i-1)+2*j-1,2*(m-1)*(i-1)+2*j-2,w);
}
}
}
for (int i = 1;i <= n-1;++i)
{
for (int j = 1;j <= m-1;++j)
{
int w;
cin >> w;
solver.addEdge(2*(m-1)*(i-1)+2*(j-1)+1,2*(m-1)*(i-1)+2*(j-1)+2,w);
solver.addEdge(2*(m-1)*(i-1)+2*(j-1)+2,2*(m-1)*(i-1)+2*(j-1)+1,w);
}
}
int ans = solver.solve(2*(n-1)*(m-1)+1,2*(n-1)*(m-1)+2,2*(n-1)*(m-1)+2);
cout << ans << endl;
return 0;
}