hdu 5352 MZL's City 最小费用最大流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5352

题意:M年前有一个国家发生了地震。所有城市和城市之间的路都被摧毁了。现在要重建城市。

给出一个N表示共有N个城市,M表示大地震发生在M年前,K表示每次最多只能重建K个城市。

现在从大地震发生的那年开始,每年可以进行一个操作,也就是总共有M个操作。

1 x表示可以重建和x联通(直接或间接)的城市(包括x本身),每次最多只能重建K个城市

2 x y 表示修建了一条城市x到城市y的路。

3操作给出一个p,表示有p条路被摧毁了,然后给出p个x和y表示城市x和y之间的路被摧毁了。

要求全部操作完成后最多能重建多少个城市(每个城市最多只能被重建一次)

并且要求输出每次重建城市操作的全部计划的最小字典序。

样例:

1
5 6 2
2 1 2 
2 1 3
1 1
1 2
3 1 1 2
1 2
表示第一年,修建了城市1和2之间的道路,第二年修建了城市1和3之间的道路。
所以第三年重建城市的时候,1和2和3都是联通的。但是因为要输出最小字典序,所以第三年不选择重建。即重建了0个城市
第四年1和2和3还是都联通的,选择重建城市1和城市3.即重建了2个城市
第五年,城市1和城市2之间的路被摧毁。
第六年,选择重建城市2,重建来1个城市。
所以总共重建了3个城市 输出 0 2 1


思路:
网络流。
在原来的基础上增加源点s和汇点t。
考虑城市,由于每个城市最多只能重建一次,所以以每个城市为点向汇点t连一条边,容量为1,费用为0.
考虑1操作。由于每次最多只能重建k个城市。所以由源点s向每个1操作连一条边,容量为K。
因为要最小字典序点方案。所以每次操作,先操作的费用大,后操作的费用小。可以设初始费用为M,然后后面每次-1.
然后对于每个1操作。再向当前可以重建的城市连一条边,容量为1,费用为0.
最后求最小费用最大流。方案就是源点向每个1操作连边的流量。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define maxn 1010
  4 const int inf = 0x3f3f3f3f;
  5 struct Edge
  6 {
  7     int from, to, cap, flow, cost;
  8     Edge(int f, int t, int ca, int fl, int co)
  9     {
 10         from = f; to = t; cap = ca; flow = fl; cost = co;
 11     }
 12 };
 13 vector <Edge> edges;
 14 vector <int> G[maxn];
 15 int n, m, s, t;
 16 int d[maxn], p[maxn], a[maxn], inq[maxn];
 17 void AddEdge(int from, int to, int cap, int cost)
 18 {
 19     edges.push_back(Edge(from, to, cap, 0, cost));
 20     edges.push_back(Edge(to, from, 0, 0, -cost));
 21     m = edges.size();
 22     G[from].push_back(m-2);
 23     G[to].push_back(m-1);
 24 }
 25 bool BellmanFord(int s, int t, int &flow, int &cost)
 26 {
 27     for(int i = 0; i <= n; i++) d[i] = inf;
 28     memset(inq, 0, sizeof(inq));
 29     d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = inf;
 30 
 31     queue<int> q;
 32     q.push(s);
 33     while(!q.empty())
 34     {
 35         int u = q.front(); q.pop();
 36         inq[u] = 0;
 37         for(int i = 0; i < G[u].size(); i++)
 38         {
 39             Edge &e = edges[G[u][i]];
 40             if(e.cap > e.flow && d[e.to] > d[u] + e.cost)
 41             {
 42                 d[e.to] = d[u] + e.cost;
 43                 p[e.to] = G[u][i];
 44                 a[e.to] = min(a[u], e.cap - e.flow);
 45                 if(!inq[e.to])
 46                 {
 47                     q.push(e.to); inq[e.to] = 1;
 48                 }
 49             }
 50         }
 51     }
 52     if(d[t] == inf) return false;
 53     flow += a[t];
 54     cost += d[t]*a[t];
 55     int u = t;
 56     while(u!=s)
 57     {
 58         edges[p[u]].flow += a[t];
 59         edges[p[u]^1].flow -= a[t];
 60         u = edges[p[u]].from;
 61     }
 62     return true;
 63 }
 64 int flow = 0;
 65 int Mincost()
 66 {
 67     int cost = 0;
 68     while(BellmanFord(s, t, flow, cost));
 69     return cost;
 70 }
 71 int T, N, M, K;
 72 int mp[220][220];
 73 vector <int> connect;
 74 int vis[maxn];
 75 void dfs(int s)
 76 {
 77     for(int i = 1; i <= N; i++)
 78     {
 79         if(mp[s][i] == 1 && !vis[i])
 80         {
 81             connect.push_back(i);
 82             vis[i] = 1;
 83             dfs(i);
 84         }
 85     }
 86     return;
 87 }
 88 int main()
 89 {
 90     scanf("%d", &T);
 91     while(T--)
 92     {
 93         scanf("%d%d%d", &N, &M, &K);
 94         edges.clear();
 95         for(int i = 0; i <= N+M+1; i++) G[i].clear();
 96         memset(mp, 0, sizeof(mp));
 97         s = 0; t = N+M+1; n = N+M+1;
 98         for(int i = 1; i <= N; i++)
 99         {    
100             mp[i][i] = 1; AddEdge(M+i, t, 1, 0);
101         }
102         int initcost = M, op, a, b, cnt = 0;
103         for(int i = 1; i <= M; i++)
104         {
105             scanf("%d", &op);
106             if(op == 1)
107             {
108                 cnt++;
109                 AddEdge(s, cnt, K, initcost);
110                 initcost--;
111                 scanf("%d", &a);
112                 connect.clear();
113                 memset(vis, 0, sizeof(vis));
114                 dfs(a);
115                 for(int j = 0; j < connect.size(); j++)
116                 {
117                     AddEdge(cnt, M+connect[j], 1, 0);
118                 }
119             }
120             else if(op == 2)
121             {
122                 scanf("%d%d", &a, &b);
123                 mp[a][b] = mp[b][a] = 1;
124             }
125             else if(op == 3)
126             {
127                 int p; scanf("%d", &p);
128                 while(p--)
129                 {
130                     scanf("%d%d", &a, &b);
131                     mp[a][b] = mp[b][a] = 0;
132                 }
133             }
134         }
135         flow = 0;
136         int cost = Mincost();
137         printf("%d
", flow);
138         bool flag = true;
139         for(int i = 0; i < m; i += 2)
140         {
141             if(edges[i].from == s)
142             {
143                 if(flag) printf("%d", edges[i].flow), flag = false;
144                 else printf(" %d", edges[i].flow);
145             }
146         }
147         printf("
");
148     }
149 }



原文地址:https://www.cnblogs.com/titicia/p/4704427.html