zoukankan      html  css  js  c++  java
  • Codeforces 976F

    题意略。

    思路:为了保证每个点都有至少k条边覆盖,我们可以让二分图的左半边与源点s相连,连容量为indegree[i] - k的边(如果正着想不好想,我们可以想它的反面,

    限制它反面的上限,从而保证我正面k条边的覆盖),让二分图的右半边与汇点t相连,容量同样是indegree[i] - k。然后跑最大流,E - 最大流中用到的边 = 答案。

    每次跑完最大流都要重新建图。我的最大流用的是dinic。

    详见代码:

    #include<bits/stdc++.h>
    #define maxn 4005
    #define INF 0x3f3f3f3f
    using namespace std;
    
    struct edge{
        int to,cap,rev,id;
        edge(int a = 0,int b = 0,int c = 0,int d = 0){
            to = a,cap = b,rev = c,id = d;
        }
    };
    
    bool visit[maxn];
    int indg[maxn],level[maxn],iter[maxn],n1,n2,m,s,t,store[maxn];
    vector<edge> graph[maxn];
    vector<edge> standard[maxn];
    
    void add_e(int from,int to,int cap,int id){
        graph[from].push_back(edge(to,cap,graph[to].size(),id));
        graph[to].push_back(edge(from,0,graph[from].size() - 1,id));
    }
    void bfs(int s){
        memset(level,-1,sizeof(level));
        queue<int> que;
        level[s] = 0;
        que.push(s);
        while(que.size()){
            int v = que.front();
            que.pop();
            for(int i = 0;i < graph[v].size();++i){
                edge& e = graph[v][i];
                if(e.cap > 0 && level[e.to] < 0){
                    level[e.to] = level[v] + 1;
                    que.push(e.to);
                }
            }
        }
    }
    int dfs(int v,int t,int f){
        if(v == t) return f;
        for(int& i = iter[v];i < graph[v].size();++i){
            edge& e = graph[v][i];
            if(e.cap > 0 && level[v] < level[e.to]){
                int d = dfs(e.to,t,min(f,e.cap));
                if(d > 0){
                    e.cap -= d;
                    graph[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
    int max_flow(int s,int t){
        int flow = 0;
        while(true){
            bfs(s);
            if(level[t] < 0) return flow;
            memset(iter,0,sizeof(iter));
            int f;
            while((f = dfs(s,t,INF)) > 0){
                flow += f;
            }
        }
    }
    
    int main(){
        scanf("%d%d%d",&n1,&n2,&m);
        s = 0,t = n1 + n2 + 1;
        for(int i = 0;i < m;++i){
            int u,v;
            scanf("%d%d",&u,&v);
            v += n1;
            ++indg[u],++indg[v];
            standard[u].push_back(edge(v,1,standard[v].size(),i + 1));
            standard[v].push_back(edge(u,0,standard[u].size() - 1,i + 1));
        }
        int mdg = maxn;
        for(int i = 1;i <= n1 + n2;++i)
            mdg = min(mdg,indg[i]);
        printf("0
    ");
        for(int k = 1;k <= mdg;++k){
            for(int v = 0;v < maxn;++v) graph[v].clear();
            for(int i = 1;i <= n1 + n2;++i){
                for(int j = 0;j < standard[i].size();++j)
                    graph[i].push_back(standard[i][j]);
            }
            for(int i = 1;i <= n1;++i) add_e(s,i,indg[i] - k,-1);
            for(int i = n1 + 1;i <= n1 + n2;++i) add_e(i,t,indg[i] - k,-1);
            max_flow(s,t);
            memset(visit,false,sizeof(visit));
            int cnt = 0;
            for(int i = n1 + 1;i <= n1 + n2;++i){
                for(int j = 0;j < graph[i].size();++j){
                    edge& e = graph[i][j];
                    if(e.cap && e.to != t){
                        visit[e.id] = true;
                        ++cnt;
                    }
                }
            }
            printf("%d",m - cnt);
            for(int i = 1;i <= m;++i){
                if(!visit[i]) printf(" %d",i);
            }
            printf("
    ");
        }
        return 0;
    }
    
    /*
    1 2 10
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 1
    1 2
    */
  • 相关阅读:
    【bzoj2962】序列操作 线段树
    【bzoj1922】[Sdoi2010]大陆争霸 堆优化Dijkstra
    .NET Core / C# 开发 IOT 嵌入式设备的个人见解
    C#中Equals和= =(等于号)的比较)
    VS 2017常用快捷键
    【你不一定知晓的】C#取消异步操作
    工程实践:给函数取一个"好"的名字
    接口测试入门篇
    博客园知名博主 Vamei 英年早逝!
    人生苦短,我用 Python
  • 原文地址:https://www.cnblogs.com/tiberius/p/9032098.html
Copyright © 2011-2022 走看看