[BZOJ1934][Shoi2007]Vote 善意的投票[最小割]

建图方式:
S->同意 ,反对->T

对于每一对好友连容量为1的边

#include <bits/stdc++.h>
using namespace std;
const int inf = 1e9;
const int MAXN = 3e2+7;
const int MAXM = 2e5+7;
int n, m, s, t, dep[MAXN], maxflow;
struct Edge {
    int v, w, next;
} G[MAXM];
int tot = 1, head[MAXN], cur[MAXN];
inline void add(int u, int v, int w) {
    G[++tot].v=v, G[tot].w=w, G[tot].next=head[u];
    head[u]=tot;
}
 
bool bfs(int s, int t) {
    memset(dep, 0x7f, sizeof dep);
    memcpy(cur+1, head+1, n*4+8);
    queue<int>q;
    while(!q.empty()) q.pop();
    dep[s] = 0;
    q.push(s);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        for(int i = head[u]; i; i = G[i].next) {
            int v = G[i].v, w = G[i].w;
            if (dep[v] > inf && w) {
                dep[v] = dep[u] + 1;
                if (v == t) return 1;
                q.push(v);
            }
        }
    }
    return dep[t] < inf;
}
 
int dfs(int u, int t, int limit) {
    if (u == t || !limit) return limit;
    int flow = 0, f;
    for(int i = cur[u]; i; i = G[i].next) {
        cur[u] = i;
        int v = G[i].v, w = G[i].w;
        if (dep[v] == dep[u] + 1 && (f = dfs(v, t, min(w, limit)))) {
            flow += f;
            limit -= f;
            G[i].w -= f;
            G[i^1].w += f;
            if (!limit) break;
        }
    }
    return flow;
}
 
void dinic(int s, int t) {
    while(bfs(s, t)) maxflow += dfs(s, t, inf);
}
 
int main(void) {
    // memset(head, -1, sizeof head);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &s);
        if (s) add(n+1, i, 1), add(i, n+1, 0);
        else add(i, n+2, 1), add(n+2, i, 0);
    }
    for(int i = 1; i <= m; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v, 1), add(v, u, 1);
//      add(u, v, 0), add(v, u, 0);//加不加都行,因为不会退流
    }
    dinic(n+1, n+2);
    printf("%d", maxflow);
    return 0;
}
posted @ 2018-12-28 16:46  QvvQ  阅读(74)  评论(0编辑  收藏