【最小割Dinic】BZOJ1163(Baltic2008)[Mafia]题解

来源:互联网 发布:iphone相片导入mac 编辑:程序博客网 时间:2024/04/27 13:37

题目概述

n 个车站, m 条双向边,封闭 i 车站的代价为 ci ,现在可以封闭若干个车站,求使得 s 无法到 t 的最小代价。

解题报告

裸的最小割问题……先拆点,然后刷最大流就行了……

示例程序

#include<cstdio>#include<cstring>#include<algorithm>#define fr first#define sc second#define mp make_pairusing namespace std;const int maxn=400,maxm=40000,MAXINT=((1<<30)-1)*2+1;int n,m,S,T;pair<int,int> e[maxm*2+5];int E,lnk[maxn+5],nxt[maxm*2+5],son[maxm*2+5];int que[maxn+5],dis[maxn+5],ti,vis[maxn+5],cur[maxn+5];inline void Add(int x,int y,int z){    son[E]=y;nxt[E]=lnk[x];e[E]=mp(0,z);lnk[x]=E++;    son[E]=x;nxt[E]=lnk[y];e[E]=mp(0,0);lnk[y]=E++;}inline bool Bfs(int S,int T){    ti++;int Head=0,Tail=0;que[++Tail]=S;dis[S]=0;vis[S]=ti;    while (Head!=Tail)        for (int x=que[++Head],j=lnk[x];~j;j=nxt[j])            if (vis[son[j]]!=ti&&e[j].fr<e[j].sc)                dis[son[j]]=dis[x]+1,vis[son[j]]=ti,que[++Tail]=son[j];    return vis[T]==ti;}int Dfs(int x,int gl,int MIN=MAXINT){    if (x==gl||!MIN) return MIN;int now=0,f=0;    for (int &j=cur[x];~j;j=nxt[j])        if (dis[x]+1==dis[son[j]]&&(now=Dfs(son[j],gl,min(e[j].sc-e[j].fr,MIN))))        {            e[j].fr+=now;e[j^1].fr-=now;            f+=now;MIN-=now;if (!MIN) break;        }    return f;}int Dinic(int S,int T){    int MAX=0;    while (Bfs(S,T)) memcpy(cur,lnk,sizeof(cur)),MAX+=Dfs(S,T);    return MAX;}int main(){    freopen("program.in","r",stdin);    freopen("program.out","w",stdout);    scanf("%d%d%d%d",&n,&m,&S,&T);S--;T--;memset(lnk,255,sizeof(lnk));    for (int i=0,x;i<n;i++) scanf("%d",&x),Add(i<<1,i<<1|1,x);    for (int i=1,x,y;i<=m;i++)    {        scanf("%d%d",&x,&y);x--;y--;        Add(x<<1|1,y<<1,MAXINT);Add(y<<1|1,x<<1,MAXINT);    }    return printf("%d\n",Dinic(S<<1,T<<1|1)),0;}