您的位置:首页 > 其它

HDU 4370 0 or 1 [01规划最短路]

2012-10-10 09:52 246 查看
  给出两个N*N的矩阵C和X,其中X是一个01矩阵,并满足以下几条,求最小的∑Cij*Xij(1<=i,j<=n)。

  1.X12+X13+...X1n=1
  2.X1n+X2n+...Xn-1n=1
  3.for each i (1<i<n), satisfies ∑Xki (1<=k<=n)=∑Xij (1<=j<=n).

  如果将C看作邻接矩阵,Xij=1实际上就是选择C中的对应边。那选出的这些点和边有什么特点呢,根据C的条件可以看出,顶点1的出度为1,顶点N的入度为1,其它点的入度=出度。这实际上就构成了一条从1到N的路径,或者从1出发走过一个环回到1,并从N出发走过一个环回到N。所以求下最短路以及两个最小环的和就可以了。

  

#include <stdio.h>
#include <string.h>
#include <queue>
#define INF 0x3f3f3f3f
#define MAXN 335
int n, map[MAXN][MAXN];
int d[MAXN], inq[MAXN];
int spfa(int s, int t, int &val){
std::queue<int> q;
memset(d, 0x3f, sizeof d);
memset(inq, 0, sizeof inq);
val = INF, d[s] = 0;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop(); inq[u] = 0;
for (int v = 0; v < n; v++) {
if (u != s && v == s) val = std::min(val, d[u] + map[u][v]);
if (d[v] > d[u] + map[u][v]) {
d[v] = d[u] + map[u][v];
if (!inq[v]) {
inq[v] = 1;
q.push(v);
}
}
}
}
return d[t];
}
int main(){
//freopen("test.in", "r", stdin);
while (scanf("%d", &n) != EOF) {
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &map[i][j]);
int s1 = 0, s2 = 0;
int ans = spfa(0, n-1, s1);
spfa(n-1, 0, s2);
printf("%d\n", std::min(ans, s1+s2));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: