HDU 4289 Control(最大流+拆点)

来源:互联网 发布:如何申请域名 编辑:程序博客网 时间:2024/06/06 02:14

题意:一个无向图,点带权值,有源点S,汇点T,问最少拆出多少权值的点使ST不连通(include S or T);

可以转化为最大流问题,将每个点P拆分成 P与P',使P->P',边权值赋为点权值,建边(P,Q)时只需连接(P',Q),(Q',P)边权值为INF即可。

跑最大流是sap(2*st,2*ed+1,2*n),一开始想错了

#include <set>#include <map>#include <stack>#include <queue>#include <deque>#include <cmath>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define L(i) i<<1#define R(i) i<<1|1#define INF  0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-9#define maxn 100100#define MOD 1000000007const int MAXN = 100010;const int MAXM = 400010;struct Edge{    int to,next,cap,flow;}edge[MAXM];int tot,n,m;int head[MAXN];int gap[MAXN],dep[MAXN];int pre[MAXN],cur[MAXN];void init(){    tot = 0;    memset(head,-1,sizeof(head));}void add_edge(int u,int v,int w,int rw = 0){    edge[tot].to = v;    edge[tot].cap = w;    edge[tot].flow = 0;    edge[tot].next = head[u];    head[u] = tot++;    edge[tot].to = u;    edge[tot].cap = rw;    edge[tot].flow = 0;    edge[tot].next = head[v];    head[v] = tot++;}int sap(int start,int en,int N){    memset(gap,0,sizeof(gap));    memset(dep,0,sizeof(dep));    memcpy(cur,head,sizeof(head));    int u = start;    pre[u] = -1;    gap[0] = N;    int ans = 0;    while(dep[start] < N)    {        if(u == en)        {            int Min = INF;            for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])                if(Min > edge[i].cap - edge[i].flow)                    Min = edge[i].cap - edge[i].flow;            for(int i = pre[u]; i != -1; i = pre[edge[i^1].to])            {                edge[i].flow += Min;                edge[i^1].flow -= Min;            }            u = start;            ans += Min;            continue;        }        int flag = 0;        int v;        for(int i = cur[u]; i != -1; i = edge[i].next)        {            v = edge[i].to;            if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])            {                flag = 1;                cur[u] = pre[v] = i;                break;            }        }        if(flag)        {            u = v;            continue;        }        int Min = N;        for(int i = head[u]; i != -1; i = edge[i].next)            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)        {            Min = dep[edge[i].to];            cur[u] = i;        }        gap[dep[u]]--;        if(!gap[dep[u]])            return ans;        dep[u] = Min + 1;        gap[dep[u]]++;        if(u != start)            u = edge[pre[u]^1].to;    }    return ans;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,C = 1;    //scanf("%d",&t);    while(scanf("%d%d",&n,&m) != EOF)    {        init();        int st,ed;        scanf("%d%d",&st,&ed);        for(int i = 1; i <= n; i++)        {            int x;            scanf("%d",&x);            add_edge(2*i,2*i+1,x);        }        for(int i = 0; i < m; i++)        {            int x,y;            scanf("%d%d",&x,&y);            add_edge(2*x+1,2*y,INF);            add_edge(2*y+1,2*x,INF);        }        printf("%d\n",sap(2*st,2*ed+1,2*n));    }    return 0;}


0 0