1. 程式人生 > 其它 >2021牛客多校 第三場 C

2021牛客多校 第三場 C

當時看了眼題意,沒怎麼想這道題

題解比較簡單,就說了求最大匹配,但是感覺實際上建圖還是有點難想的

正解:
這道題實際上就是拿最小的代價去滿足行與列上的最大值要求,所以實際上下面給出的點裡很多都是無所謂的,關鍵是那些行最大值等於列最大值的點,因為他們可以同時滿足兩個值,以此減少整體的總和。

因此,這道題我們只需要把這些點提取出來,然後根據最大值值來做,如果某一最大值下,沒有任何點可以使行列同時滿足,那麼要達到這些最大值只能每行每列都取一個這個值,如果有點能夠把行上的該最大值和列上的最大值連線起來,那麼就能減少一,所以我們根據之前存下的點產生的連線關係,對這張對於每個最大值建的二分圖連線一下,然後求一個最大匹配,就能知道最多可以省下多少個最大值,然後對於每個最大值建立的圖求和就行。

下附程式碼:

  1 #include<bits/stdc++.h>
  2 #define maxn 250
  3 #define ll long long
  4 #define INF 0x3f3f3f3f
  5 using namespace std;
  6 struct Edge {
  7     int from, to, cap, flow;
  8     Edge(int u, int v, int c, int f) : from(u), to(v), cap(c), flow(f) {}
  9 };
 10 struct Dinic {
 11     int
n, m, s, t; 12 vector<Edge> edges; 13 vector<int> G[maxn]; 14 int d[maxn], cur[maxn]; 15 bool vis[maxn]; 16 void init(int n) { 17 for (int i = 0; i < n; i++) G[i].clear(); 18 edges.clear(); 19 } 20 void AddEdge(int from, int to, int cap) { 21
edges.push_back(Edge(from, to, cap, 0)); 22 edges.push_back(Edge(to, from, 0, 0)); 23 m = edges.size(); 24 G[from].push_back(m - 2); 25 G[to].push_back(m - 1); 26 } 27 bool BFS() { 28 memset(vis, 0, sizeof(vis)); 29 queue<int> Q; 30 Q.push(s); 31 d[s] = 0; 32 vis[s] = 1; 33 while (!Q.empty()) { 34 int x = Q.front(); 35 Q.pop(); 36 for (int i = 0; i < G[x].size(); i++) { 37 Edge& e = edges[G[x][i]]; 38 if (!vis[e.to] && e.cap > e.flow) { 39 vis[e.to] = 1; 40 d[e.to] = d[x] + 1; 41 Q.push(e.to); 42 } 43 } 44 } 45 return vis[t]; 46 } 47 int DFS(int x, int a) { 48 if (x == t || a == 0) return a; 49 int flow = 0, f; 50 for (int& i = cur[x]; i < G[x].size(); i++) { 51 Edge& e = edges[G[x][i]]; 52 if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0){ 53 e.flow += f; 54 edges[G[x][i] ^ 1].flow -= f; 55 flow += f; 56 a -= f; 57 if (a == 0) break; 58 } 59 } 60 return flow; 61 } 62 int Maxflow(int s, int t) { 63 this->s = s; 64 this->t = t; 65 int flow = 0; 66 while (BFS()) { 67 memset(cur, 0, sizeof(cur)); 68 flow += DFS(s, INF); 69 } 70 return flow; 71 } 72 }flow; 73 map<int,int> mph,mpl; 74 vector<pair<int,int>> v[1000005]; 75 int a[2005],b[2005]; 76 int ch[1000005],cl[1000005]; 77 int main(){ 78 int n,m,k; 79 scanf("%d%d%d",&n,&m,&k); 80 for (int i=1; i<=n; i++){ 81 scanf("%d",&a[i]); 82 ch[a[i]]++; 83 } 84 for (int i=1; i<=n; i++){ 85 scanf("%d",&b[i]); 86 cl[b[i]]++; 87 } 88 for (int i=1; i<=m; i++){ 89 int x,y; 90 scanf("%d%d",&x,&y); 91 if (a[x]==b[y]){ 92 v[a[x]].push_back({x,y}); 93 } 94 } 95 ll res=0; 96 for (int i=k; i>=0; i--){ 97 if (cl[i]!=0 || ch[i]!=0){ 98 mph.clear(); 99 mpl.clear(); 100 flow.init(cl[i]+ch[i]+2); 101 for (int j=1; j<=ch[i]; j++){ 102 flow.AddEdge(0,j,1); 103 } 104 for (int j=1; j<=cl[i]; j++){ 105 flow.AddEdge(j+ch[i],cl[i]+ch[i]+1,1); 106 } 107 int st1=0,st2=ch[i]; 108 for (int j=0; j<v[i].size(); j++){ 109 if (!mph[v[i][j].first]) mph[v[i][j].first]=++st1; 110 if (!mpl[v[i][j].second]) mpl[v[i][j].second]=++st2; 111 flow.AddEdge(mph[v[i][j].first],mpl[v[i][j].second],1); 112 } 113 int maxflow=flow.Maxflow(0,cl[i]+ch[i]+1); 114 res+=i*(ch[i]+cl[i]-maxflow); 115 } 116 } 117 printf("%lld",res); 118 }
View Code