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 }
View Code

相关文章: