Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 13514 | Accepted: 5128 |
Description
Input
Output
Sample Input
4 5 1 2 1 2 3 1 3 4 1 1 3 2 2 4 2
Sample Output
6
题意:
给你N个农田、M条无向边以及每条边的长度。现在让你从1走到N再从N走回1,要求不能走重复的边。问你所走的路径总长的最小值。题目保证1到N至少会存在两条边不重复的路径。
解析:
很常规的思路,就简单说一下建图过程。
设一个超级源点 outset,超级汇点inset。
(1)源点到1建边,容量为2,费用为0。
(2) 对每条可达的无向边建边,容量为1,费用为边的权值,这点主要要建双向边。
(3)n到汇点建边,容量为2,费用为0。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define maxn 2200 #define maxm 110000 #define INF 0x3f3f3f3f using namespace std; int n, m; int inset, outset; int sum; struct node { int u, v, cap, flow, cost, next; }; node edge[maxm]; int head[maxn], cnt; int dist[maxn], vis[maxn]; int per[maxn]; void init(){ cnt = 0; memset(head, -1, sizeof(head)); } void add(int u, int v, int w, int c){ node E1 = {u, v, w, 0, c, head[u]}; edge[cnt] = E1; head[u] = cnt++; node E2 = {v, u, 0, 0, -c, head[v]}; edge[cnt] = E2; head[v] = cnt++; } void getmap(){ int a, b, c; outset = 0; inset = n + 1; while(m--){ scanf("%d%d%d", &a, &b, &c); add(a, b, 1, c); add(b, a, 1, c); } add(outset, 1, 2, 0); add(n, inset, 2, 0); } bool SPFA(int st, int ed){ queue<int>q; for(int i = 0; i <= inset; ++i){ dist[i] = INF; vis[i] = 0; per[i] = -1; } dist[st] = 0; vis[st] = 1; q.push(st); while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; i != -1; i = edge[i].next){ node E = edge[i]; if(dist[E.v] > dist[u] + E.cost && E.cap > E.flow){ dist[E.v] = dist[u] + E.cost; per[E.v] = i; if(!vis[E.v]){ vis[E.v] = 1; q.push(E.v); } } } } return per[ed] != -1; } void MCMF(int st, int ed, int &cost, int &flow){ flow = 0; cost = 0; while(SPFA(st, ed)){ int mins = INF; for(int i = per[ed]; i != -1; i = per[edge[i ^ 1].v]){ mins = min(mins, edge[i].cap - edge[i].flow); } for(int i = per[ed]; i != -1; i = per[edge[i ^ 1].v]){ edge[i].flow += mins; edge[i ^ 1].flow -= mins; cost += edge[i].cost * mins; } flow += mins; } } int main (){ while(scanf("%d%d", &n, &m) != EOF){ init(); getmap(); int cost, flow; MCMF(outset, inset, cost, flow); printf("%d\n", cost); } return 0; }