• Educational Codeforces Round 43 (Rated for Div. 2)题解


    ABC 喵喵喵

    D

    数学归纳吖!

    • n=0 ok
    • n=1 ok 形成d[1]+1个点的完全图
    • n>2 一定能到达比n更小的状态
      d[n],d[n-1]....d[1] -> d[n-1]-d[1],d[n-2]-d[1],...d[2]-d[1]

    E

    • 不考虑A操作,只考虑B操作:排序+贪心。
    • 考虑A操作,会发现a全部加到一个人身上是最好的。
    • 枚举把a加到哪个人头上。

    F

    • 二分图的最小边覆盖 = V - MaxMatch
    • 最大匹配前是个负号哎!那没有被最大流浸泡过的边会不会就是答案呢?
    • Hint:源点向左集连容量为deg-k的边

    code

    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstring>
    #include <vector>
    
    using namespace std;
    const int N = 5000 + 10;  
    const int INF = 1e9 + 7;  
    #define mp(x,y) make_pair(x,y)
      
    struct Edge {  
        int from , to , cap , flow, id;  
    };  
    bool visit[N];
    struct Dinic {   
        int n,m,s,t;  
        vector<Edge> edges;  
        vector<int> f[N];  
        bool vis[N];  
        int d[N];  
        int cur[N];   
        void init(int n) {
            this->n = n;
            edges.clear();
            for (int i = 0; i < N; i ++) f[i].clear();
            memset(d, 0, sizeof(d));
            memset(cur, 0, sizeof(cur));
            memset(visit, 0, sizeof(visit));
        }
        void AddEdge(int from,int to,int cap,int id)  
        {  
            edges.push_back((Edge){from,to,cap,0,id});  
            edges.push_back((Edge){to,from,0,0,id});  
            m = edges.size();  
            f[from].push_back(m-2);  
            f[to].push_back(m-1);  
        }  
        bool BFS()   
        {  
            memset(vis,0,sizeof(vis));  
            queue<int> q;  
            q.push(s);  
            d[s] = 0;  
            vis[s] = 1;     
            while(!q.empty())  
            {  
                int x = q.front(); q.pop();  
                for(int i=0;i<f[x].size();i++)  
                {  
                    Edge &e = edges[f[x][i]];  
                    //cout<<"to="<<e.to<<"from="<<e.from<<' '<<e.flow<<' '<<e.cap<<' '<<vis[e.to]<<endl;  
                    if(!vis[e.to] && e.flow < e.cap) //只考虑残留网络中的弧   
                    {  
                        vis[e.to] = 1;  
                        d[e.to] = d[x] + 1;//层次图  
                        q.push(e.to);   
                    }  
                }  
            }  
            return vis[t];//能否到汇点,不能就结束   
        }  
        int DFS(int x,int a)//x为当前节点,a为当前最小残量   
        {  
            if(x == t || a == 0) return a;  
            int flow = 0 , r;  
              
            for(int& i = cur[x];i < f[x].size();i++)  
            {  
                Edge& e = edges[f[x][i]];  
                if(d[x] + 1 == d[e.to] && (r = DFS(e.to , min(a,e.cap - e.flow) ) ) > 0 )  
                {  
                    e.flow += r;  
                    edges[f[x][i] ^ 1].flow -= r;  
                    //get Ans
                    //printf("miao: %d
    ", edges[f[x][i] ^ 1].id);
                    //visit[edges[f[x][i] ^ 1].id] = 1;
    
                    flow += r;//累加流量   
                    a -= r;  
                    if(a == 0) break;  
                }  
            }  
            return flow;  
        }  
        int MaxFlow(int s,int t)  
        {  
            this->s = s; this->t = t;  
            int flow = 0;  
            while(BFS())  
            {      
                memset(cur,0,sizeof(cur));  
                flow += DFS(s,INF);  
                //printf("%d
    ", flow);
            }  
            for (int i=0;i<edges.size();i++) {
                if (edges[i].flow) visit[edges[i].id] = 1;
            }
            return flow;  
        }  
    } G;
    
    int n1,n2,m,deg[N];
    vector< pair<int, int> > v[N];
    
    void build_gragh(int k) {
        int S = n1+n2+1, T=n1+n2+2;
        G.init(T+2);
        for(int i=1;i<=n1;i++) {
            G.AddEdge(S,i,deg[i]-k,0);
        }
        for(int i=1;i<=n2;i++) {
            G.AddEdge(i+n1,T,deg[i+n1]-k,0);
        }
        for(int i=1;i<=n1;i++) {
            for (int j=0;j<v[i].size();j++) {
                G.AddEdge(i,v[i][j].first+n1,1,v[i][j].second);
            }
        }
        int ret = G.MaxFlow(S,T);
    
        printf("%d ", m-ret);
        for (int i=1;i<=m;i++) {
            if (visit[i] == 0) 
                printf("%d ", i);
        }
        printf("
    ");
    }
    
    int main() {
        scanf("%d%d%d",&n1,&n2,&m);
        for(int i=1;i<=m;i++) {
            int x, y; 
            scanf("%d%d",&x,&y);
            v[x].push_back(mp(y, i));
            deg[x] ++, deg[n1+y]++;
        }
        printf("0
    ");
        int mnDegree = *min_element(deg+1,deg+1+n1+n2);
        for (int i = 1; i <= mnDegree; i ++) {
            build_gragh(i);
        }
    }
    
    
  • 相关阅读:
    【bzoj2190】: [SDOI2008]仪仗队 数论-欧拉函数
    【bzoj2751】[HAOI2012]容易题(easy) 数论-快速幂
    【bzoj2186】: [Sdoi2008]沙拉公主的困惑 数论-欧拉函数
    这里会有你想要的,已收录css , js相关文章
    Vue源码解析--实现一个指令解析器 Compile
    九宫格抽奖
    12行代码简单实现跑马灯文字匀速滚动
    滑弯曲弧形效果的插件-arctext.js改造
    几种拼图小游戏封装
    倒计时
  • 原文地址:https://www.cnblogs.com/RUSH-D-CAT/p/9009556.html
Copyright © 2020-2023  润新知