• 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
  • 相关阅读:
    电子商务测试点总结
    pc 端 测试点总结
    web测试点总结
    Monkey脚本API
    Git 命令
    配置samba的流程
    scrapy使用指南
    链接
    顺序表总结
    python数据类型——字符串类型
  • 原文地址:https://www.cnblogs.com/i-caigou-TT/p/15058035.html
Copyright © 2020-2023  润新知