zoukankan      html  css  js  c++  java
  • bzoj 1934最小割

      比较显然的最小割的题,增加节点source,sink,对于所有选1的人我们可以(source,i,1),选0的人我们可以(i,sink,1),然后对于好朋友我们可以连接(i,j,1)(j,i,1),然后我们求最小割就好了,因为我们可以将节点分为两部分,表示0,1的选法,那么我们割一条与sink,source连的边表示这个人与自己的意愿不同,需要1的代价,如果两个人连边,这两个人不在同一集合,那么这两个人割掉连边需要1的代价。

    /**************************************************************
        Problem: 1934
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:20 ms
        Memory:3156 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxm 100010
    #define maxn 400
    #define inf (~0U>>1)
     
    using namespace std;
     
    int n,m,source,sink,l,ans;
    int last[maxn],other[maxm<<1],len[maxm<<1],pre[maxm<<1],flag[maxn];
    int que[maxn],d[maxn];
     
    void connect(int x,int y,int z) {
        pre[++l]=last[x];
        last[x]=l;
        other[l]=y;
        len[l]=z;
    }
     
    bool bfs() {
        memset(d,0,sizeof d);
        que[1]=source; d[source]=1; 
        int h=0,t=1;
        while (h<t) {
            int cur=que[++h];
            for (int p=last[cur];p;p=pre[p]) {
                if (d[other[p]]) continue;
                if (!len[p]) continue;
                d[other[p]]=d[cur]+1;
                que[++t]=other[p];
                if (other[p]==sink) return 1;
            }
        }
        return 0;
    }
     
    int dinic(int x,int flow) {
        if (x==sink) return flow;
        int rest=flow;
        for (int p=last[x];p;p=pre[p]) {
            if (!len[p]) continue;  
            if (d[other[p]]!=d[x]+1) continue;
            if (!rest) continue;
            int tmp=dinic(other[p],min(len[p],rest));
            if (!tmp) d[other[p]]=0;
            len[p]-=tmp; len[p^1]+=tmp;
            rest-=tmp;
        }
        return flow-rest;
    }
     
     
    int main() {
        scanf("%d%d",&n,&m); 
        source=n+2; sink=source+1; l=1;
        for (int i=1;i<=n;i++) {
            scanf("%d",&flag[i]);
            if (flag[i]) connect(source,i,1),connect(i,source,0); else
                connect(i,sink,1),connect(sink,i,0);
        }
        for (int i=1;i<=m;i++) {
            int x,y; scanf("%d%d",&x,&y);
            connect(x,y,1); connect(y,x,0);
            connect(y,x,1); connect(x,y,0);
        }
        while (bfs()) ans+=dinic(source,inf);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    hbase权威指南PDF下载
    流畅的pythonPDF下载
    现代操作系统PDF下载
    Kafka权威指南PDF下载
    java核心技术卷1PDF下载
    计算机网络自顶向下方法PDF下载
    git gitlab 部署
    MySQL 索引、事务与存储引擎(详细解读)
    QT: Layout布局间消除间隙(修改layout内置参数)
    数据结构---归并排序
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3677785.html
Copyright © 2011-2022 走看看