分析:
给出N个点和M条路,每条路有一个长度,而且从一个点到另外一个点可能不止一条路,要求从1走到N再走回去,并且同一条路只能走一次,求最短路径的长度。题解:
- 建图:首先,因为有重边的情况存在,所以需要用邻接链表来存储边,然后因为是无向边,所以每条边需要正着建一次,反着建一次。
因为走过去又走回来且不能走相同的路,就相当于一个网络流:每条路的流量为1,源点到点1的流量为2,点N到汇点的流量为2,这样就能用最大流最小费用的算法求出结果了!
- 建图:首先,因为有重边的情况存在,所以需要用邻接链表来存储边,然后因为是无向边,所以每条边需要正着建一次,反着建一次。
#define MaxN 2222
#define MaxM MaxN*40
#define INF 100000000
int N,M;
struct node
{
int u,v,next,flow,cost;
}edge[MaxM];
int head[MaxN];
int cont;
int n;
void add(int u, int v, int flow, int cost)
{
edge[cont].v = v;
edge[cont].u = u;
edge[cont].flow = flow;
edge[cont].cost = cost;
edge[cont].next = head[u];
head[u] = cont++;
}
void Add(int u, int v, int flow, int cost)
{
add(u, v, flow, cost); //正向边
add(v, u, 0, -cost); //反向退流边
}
//建图:
int a,b,c;
for(int i=0;i<M;i++)
{
scanf("%d%d%d", &a, &b, &c);
Add(a,b,1,c);
Add(b,a,1,c);
}
Add(0,1,2,0);
Add(N,N+1,2,0);
- AC代码:
/*************************************************************************
> File Name: FarmTourHDU2135.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
> Created Time: 2016年08月12日 星期五 11时01分29秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <set>
#include <list>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;
#define MaxN 2222
#define MaxM MaxN*40
#define INF 100000000
int N,M;
struct node
{
int u,v,next,flow,cost;
}edge[MaxM];
int head[MaxN];
int cont;
int n;
void add(int u, int v, int flow, int cost)
{
edge[cont].v = v;
edge[cont].u = u;
edge[cont].flow = flow;
edge[cont].cost = cost;
edge[cont].next = head[u];
head[u] = cont++;
}
void Add(int u, int v, int flow, int cost)
{
add(u, v, flow, cost);
add(v, u, 0, -cost);
}
void init()
{
MST(head,-1);
cont = 0;
n = 0;
}
bool vis [MaxN];
int dist [MaxN];
int pre [MaxN];
int aug;
int ans;
bool SPFA(int s, int t)
{
int k, p, V;
queue<int> q;
MST(pre, -1);
CLR(vis);
for(int i=0;i<=n;i++)
dist[i] = INF;
q.push(s);
vis[s] = 1;
dist[s] = 0;
while(!q.empty())
{
k = q.front();
q.pop();
vis[k] = 0;
for(p = head[k]; p!=-1; p = edge[p].next)
{
V = edge[p].v;
if(edge[p].flow && (edge[p].cost + dist[k] < dist[V]))
{
dist[V] = edge[p].cost + dist[k];
pre[V] = p;
if(!vis[V])
{
q.push(V);
vis[V] = 1;
}
}
}
}
if(dist[t] == INF) return false;
aug = INF+1;
for(p = pre[t]; p != -1; p = pre[edge[p].u])
{
aug = min(aug, edge[p].flow);
}
for(p = pre[t]; p != -1; p = pre[edge[p].u])
{
edge[p].flow -= aug;
edge[p^1].flow += aug;
}
// cout << ans << endl;
ans += dist[t]*aug;
return true;
}
int main()
{
while(~scanf("%d%d", &N, &M))
{
init();
int a,b,c;
for(int i=0;i<M;i++)
{
scanf("%d%d%d", &a, &b, &c);
Add(a,b,1,c);
Add(b,a,1,c);
}
Add(0,1,2,0);
Add(N,N+1,2,0);
int Ans = 0;
n = N+1;
ans = 0;
while(SPFA(0,N+1));
Ans += ans;
cout << Ans << endl;
}
return 0;
}