A Birthday
思路:设置一个源点,一个汇点,每次对$源点对a_i, b_i , a_i 对 b_i 连一条流为1,费用为0的边$
每个点都再连一条 1, 3, 5, 7, ....的边到汇点之间,因为每多加一个流的费用,然后就是最小费用最大流
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 const int INF = 0x3f3f3f3f; 6 7 const int maxn = 1010; 8 const int maxm = 10010; 9 10 struct Edge{ 11 int to, nxt, cap, flow, cost; 12 }edge[maxm]; 13 14 int head[maxn], tot; 15 int pre[maxn], dis[maxn]; 16 bool vis[maxn]; 17 int N; 18 19 void Init(int n) 20 { 21 N = n; 22 tot = 0; 23 memset(head, -1, sizeof head); 24 } 25 26 void addedge(int u, int v, int cap, int cost) 27 { 28 edge[tot].to = v; 29 edge[tot].cap = cap; 30 edge[tot].cost = cost; 31 edge[tot].flow = 0; 32 edge[tot].nxt = head[u]; 33 head[u] = tot++; 34 35 edge[tot].to = u; 36 edge[tot].cap = 0; 37 edge[tot].cost = -cost; 38 edge[tot].flow = 0; 39 edge[tot].nxt = head[v]; 40 head[v] = tot++; 41 } 42 43 bool SPFA(int s, int t) 44 { 45 queue<int>q; 46 for(int i = 0; i < N; ++i) 47 { 48 dis[i] = INF; 49 vis[i] = false; 50 pre[i] = -1; 51 } 52 dis[s] = 0; 53 vis[s] = true; 54 q.push(s); 55 while(!q.empty()) 56 { 57 int u = q.front(); 58 q.pop(); 59 vis[u] = false; 60 for(int i = head[u]; ~i; i = edge[i].nxt) 61 { 62 int v = edge[i].to; 63 if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) 64 { 65 dis[v] = dis[u] + edge[i].cost; 66 pre[v] = i; 67 if(!vis[v]) 68 { 69 vis[v] = true; 70 q.push(v); 71 } 72 } 73 } 74 } 75 if(pre[t] == -1) return false; 76 else return true; 77 } 78 79 int solve(int s,int t) 80 { 81 int flow = 0 ; 82 int cost = 0; 83 while(SPFA(s, t)) 84 { 85 int Min = INF; 86 for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to]) 87 { 88 Min = min(Min, edge[i].cap - edge[i].flow); 89 } 90 for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to]) 91 { 92 edge[i].flow += Min; 93 edge[i ^ 1].flow -= Min; 94 cost += edge[i].cost * Min; 95 } 96 flow += Min; 97 } 98 return cost; 99 } 100 101 int n, m; 102 103 int main() 104 { 105 while(~scanf("%d %d", &n, &m)) 106 { 107 Init(n + m + 2); 108 int s = 0, t = n + m + 1; 109 for(int i = 1; i <= n; ++i) 110 { 111 int u, v; 112 scanf("%d %d", &u, &v); 113 addedge(0, i, 1, 0); 114 addedge(i, u + n, 1, 0); 115 addedge(i, v + n, 1, 0); 116 } 117 for(int i = n + 1; i <= n + m; ++i) 118 { 119 for(int j = 1; j < 100; j += 2) 120 { 121 addedge(i, t, 1, j); 122 } 123 } 124 int cost = solve(0, n + m + 1); 125 printf("%d\n", cost); 126 } 127 return 0; 128 }