题意:一个人带领一位朋友游历他的牧场,他的房子在第一个点,仓库在第N个点。求解从第一个点出发到达第n个点后在返回,最短的路径,每个点只能走一次。
思路:费用流。建图:源点与第一个点建一条边花费2,流量0。第n个点与汇建立一条边,费用2,流量0,其他各点建图,费用1,流量为给出值。用MFMC模板求解。
#include<stdio.h> #include<string.h> #include<queue> #include<math.h> #include<iostream> using namespace std; #define inf 0xfffffff #define M 1005 struct node { int x, y; }; int tem[M][M]; int n, m, len; struct edge { int v, w, flow, c, next; } edge[M * M * 10]; int vst[M], dis[M], head[M], pre[M];//dis记录路径长度 int tot, flow_sum; void add(int v, int w, int f, int c) { edge[tot].v = v; edge[tot].w = w; edge[tot].flow = f; edge[tot].c = c; edge[tot].next = head[v]; head[v] = tot++; edge[tot].v = w; edge[tot].w = v; edge[tot].flow = 0; edge[tot].c = -c; edge[tot].next = head[w]; head[w] = tot++; } //MCMF开始 bool spfa(int begin, int end) //spfa求解最短路径,即增广链中最小费用 { int v, w; queue < int >q; for (int i = 0; i <= end + 2; i++) { pre[i] = -1; vst[i] = 0; dis[i] = inf; } vst[begin] = 1; dis[begin] = 0; q.push(begin); while (!q.empty()) { v = q.front(); q.pop(); vst[v] = false; for (int i = head[v]; i != -1; i = edge[i].next) { if (edge[i].flow > 0) { w = edge[i].w; if (dis[w] > dis[v] + edge[i].c) { dis[w] = dis[v] + edge[i].c; pre[w] = i; if (!vst[w]) { vst[w] = true; q.push(w); } } } } } return dis[end] != inf; } int MCMF(int begin, int end) { int ans = 0, flow, i; flow_sum = 0; while (spfa(begin, end)) { flow = inf; for (i = pre[end]; i != -1; i = pre[edge[i].v]) if (edge[i].flow < flow) flow = edge[i].flow;//找增广链上所有边的容量的最小值作为“可分配最大流” for (i = pre[end]; i != -1; i = pre[edge[i].v]) { edge[i].flow -= flow; //正向弧加 edge[i^1].flow += flow; //反向弧减 } ans += dis[end]; flow_sum += flow; //总流量 } // cout << flow_sum << endl; return ans; // 返回最小费用 } int main() { int i, j; int s,e,c; while (scanf("%d%d", &n, &m) != EOF) { tot = 0; memset(head, -1, sizeof (head)); for (i = 1; i <=m; i++) { cin>>s>>e>>c; add(s,e,1,c); add(e,s,1,c); } add(0, 1, 2, 0); add(n, n+1, 2, 0); cout << MCMF(0, n + 1) << endl; } return 0; } /* 4 5 1 2 1 2 3 1 3 4 1 1 3 2 2 4 2 4 5 1 2 2 2 3 1 3 4 1 1 3 2 2 4 2 6 7 */