1.题目链接。题目大意:给定一个n个点m条边的无向图,每条边都有一个长度,求从1->n->1走过的长度最小值并且每条边只能走一次。
2.由于边是无向的,其实这个题目就是在问从1到n两条不相交的路径的长度之和最小值。考虑把长度作为费用,就转化成了一个每条边的容量为1的费用里问题,建立源点s,到1的流量为2,费用为0,汇点t。到n的流量为2,费用为0,所以就成了s,到t的MCMF。
using namespace std;
const int inf = 1 << 29;
const int MAXN = 1010;
const int MAXM = 40010;
struct Node
{
int s;
int to;
int next;
int capacity;
int value;
};
int n, m;
int index;
Node node[MAXM];
int head[MAXN];
int pre[MAXN];
int dis[MAXN];
bool vis[MAXN];
void init()
{
index = 0;
memset(head, -1, sizeof(head));
memset(node, 0, sizeof(node));
}
void addedge(int a, int b, int v, int c)
{
node[index].to = b;
node[index].s = a;
node[index].value = v;
node[index].capacity = c;
node[index].next = head[a];
head[a] = index++;
node[index].to = a;
node[index].s = b;
node[index].value = -v;
node[index].capacity = 0;
node[index].next = head[b];
head[b] = index++;
}
bool spfa(int s, int t, int nnum)
{
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
for (int i = 0; i <= nnum; i++)
{
dis[i] = inf;
}
queue<int> que;
que.push(s);
dis[s] = 0;
vis[s] = true;
while (!que.empty())
{
int temp = que.front();
que.pop();
vis[temp] = false;
for (int i = head[temp]; i != -1; i = node[i].next)
{
if (node[i].capacity)
{
int ne = node[i].to;
if (dis[temp] + node[i].value < dis[ne])
{
dis[ne] = dis[temp] + node[i].value;
pre[ne] = i;
if (!vis[ne])
{
vis[ne] = true;
que.push(ne);
}
}
}
}
}
if (dis[t] == inf)
return false;
return true;
}
int getMincost(int s, int t, int nnum)
{
int ans_flow = 0;
int ans_cost = 0;
int temp, minc;
while (spfa(s, t, nnum))
{
temp = t;
minc = inf;
while (pre[temp] != -1)
{
minc = min(node[pre[temp]].capacity, minc);
temp = node[pre[temp]].s;
}
temp = t;
while (pre[temp] != -1)
{
node[pre[temp]].capacity -= minc;
int ss = pre[temp] ^ 1;
node[ss].capacity += minc;
temp = node[pre[temp]].s;
}
ans_cost += dis[t] * minc;
}
return ans_cost;
}
int main()
{
int a, b, v;
int s, t, result;
while (cin >> n >> m)
{
init();
for (int i = 0; i < m; i++)
{
cin >> a >> b >> v;
//a->b的费用是v,流量是0
addedge(a, b, v, 1);
addedge(b, a, v, 1);
}
s = n + 1;
t = s + 1;
addedge(s, 1, 0, 2);
addedge(n, t, 0, 2);
result = getMincost(s, t, t);
cout << result << endl;
}
return 0;
}