6 9 1 2 5 2 3 5 3 1 10 3 4 12 4 1 8 4 6 11 5 4 7 5 6 9 6 5 4 6 5 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1
42 -1HintIn the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20 + 22 = 42.
水一遍熟悉熟悉模板。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define INF 0x3f3f3f3f #define maxn 500 #define maxm 77000 using namespace std; int n, m; int outset; int inset; struct node { int u, v, cap, flow, cost, next; }; node edge[maxm]; int head[maxn], cnt; int per[maxn];//记录增广路径上 到达点i的边的编号 int dist[maxn], vis[maxn]; void init(){ cnt = 0; memset(head, -1, sizeof(head)); } void add(int u, int v, int w, int c){ int i; for(i = head[u]; i != -1; i = edge[i].next){ node E = edge[i]; if(v == E.v) break; } if(i != -1){ if(edge[i].cost > c) edge[i].cost = c, edge[i ^ 1].cost = -c; return ; } //edge[cnt] = {u, v, w, 0, c, head[u]}这样写就直接超时了。 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(){ outset = 0; inset = n * 2 + 1; for(int i = 1; i <= n; ++i){ add(outset, i, 1, 0); add(i + n, inset, 1, 0); } while(m--){ int a, b, c; scanf("%d%d%d", &a, &b, &c); add(a, b + n, 1, c); } } 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); if(flow == n) printf("%d\n", cost); else printf("-1\n"); } return 0; }