虽然我很不喜欢邻接表,但是不可否认邻接表对于稀疏图和有多重边图的处理还是比邻接矩阵要好,所以还是要学~~
这道题又让我见识到了网络流的强大......建图思路:先将长度为len的边建为容量为1,费用为len的图,这样容量为1保证每条路只走一次;然后选取一源点和汇点,将原点与第一个顶点相连,汇点与第N个顶点相连,这样可以等价从1到N,再从N回到1。YM第一个想出思路的大牛!
邻接表模版网上好多,搜了一个学习了学习,终于理解了,把这道题成功a掉~~
代码如下:
Problem: 2135 User: jiaolinfeng
Memory: 20664K Time: 94MS
Language: G++ Result: Accepted
#include<iostream>
#include<cstdio>
#include<cstring>
#include<climits>
#include<queue>
#define MAXN 1010
using namespace std;
int N, M, cnt;
typedef struct
{
int u, v, cost, cap;
int next;
}Node;
Node node[MAXN*MAXN];
int tour[MAXN];
int dis[MAXN];
int pre[MAXN];
int re[MAXN];
int inq[MAXN];
void init()
{
cnt = 2;
memset(tour, 0, sizeof(tour));
memset(node, 0, sizeof(node));
}
void Add(int from, int to, int cap, int cost)
{
node[cnt].u = from;
node[cnt].v = to;
node[cnt].cap = cap;
node[cnt].cost = cost;
node[cnt].next = tour[from];
tour[from] = cnt++;
node[cnt].u = to;
node[cnt].v = from;
node[cnt].cap = 0;
node[cnt].cost = -cost;
node[cnt].next = tour[to];
tour[to] = cnt++;
}
int MinCostMaxFlow(int s, int t)
{
int c = 0, ind, cap, u, v, cost;
queue<int> q;
for(;;)
{
for(int i = s; i <= t; i++)
{
dis[i] = INT_MAX;
}
dis[s] = 0;
memset(inq, 0, sizeof(inq));
q.push(s);
inq[s] = 1;
pre[s] = s;
while(!q.empty())
{
u = q.front();
q.pop();
inq[u] = 0;
ind = tour[u];
while(ind != 0)
{
cap = node[ind].cap;
u = node[ind].u;
v = node[ind].v;
cost = node[ind].cost;
if(cap > 0 && dis[v] > dis[u] + cost)
{
dis[v] = dis[u] + cost;
pre[v] = u;
re[v] = ind;
if(!inq[v])
{
q.push(v);
inq[v] = 1;
}
}
ind = node[ind].next;
}
}
if(dis[t] == INT_MAX)
break;
for(u = t; u != s; u = pre[u])
{
// printf("%d %d\n", pre[u], u);
node[re[u]].cap -= 1;
node[re[u]^1].cap += 1;
}
c += dis[t];
}
return c;
}
int main()
{
int i, j, a, b, c;
while(scanf("%d%d", &N, &M) != EOF)
{
init();
for(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);
printf("%d\n", MinCostMaxFlow(0, N+1));
}
return 0;
}