传送门:Control
题意:有n个城市,有个小偷想从其中一个城市逃到另一个城市,警察想要堵截这个小偷,知道了在每个城市堵截的成本,问如何安排在哪些城市堵截可以使得小偷一定会被抓住,而且成本最低。
分析:根据割的定义将整部图分成两部分且互不相通,这题明显是求最小割,根据最小割等于最大流,则拆点后直接求最大流即可,对于点值在最大流中的限制经常是拆点处理。
#pragma comment(linker,"/STACK:1024000000,1024000000") #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <limits.h> #include <iostream> #include <algorithm> #include <queue> #include <cstdlib> #include <stack> #include <vector> #include <set> #include <map> #define LL long long #define mod 100000000 #define inf 0x3f3f3f3f #define eps 1e-6 #define N 100010 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define PII pair<int,int> using namespace std; inline int read() { char ch=getchar(); int x=0,f=1; while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int n,m,vs,vt,tot,NV; int head[N],gap[N],level[N],q[N]; struct edge { int v,w,next; edge(){} edge(int v,int w,int next):v(v),w(w),next(next){} }e[N<<1]; void addedge(int u,int v,int w) { e[tot]=edge(v,w,head[u]); head[u]=tot++; e[tot]=edge(u,0,head[v]); head[v]=tot++; } void init() { memset(head,-1,sizeof(head)); tot=0; } /***************************SAP***********************/ void bfs(int vt) { memset(level,-1,sizeof(level)); memset(gap,0,sizeof(gap)); level[vt]=0; gap[level[vt]]++; queue<int>que; que.push(vt); while(!que.empty()) { int u=que.front(); que.pop(); for(int i=head[u]; i!=-1; i=e[i].next) { int v=e[i].v; if(level[v]!=-1)continue; level[v]=level[u]+1; gap[level[v]]++; que.push(v); } } } int pre[N]; int cur[N]; int SAP() { bfs(vt); memset(pre,-1,sizeof(pre)); memcpy(cur,head,sizeof(head)); int u=pre[vs]=vs,flow=0,aug=inf; gap[0]=NV; while(level[vs]<NV) { bool flag=false; for(int &i=cur[u]; i!=-1; i=e[i].next) { int v=e[i].v; if(e[i].w&&level[u]==level[v]+1) { flag=true; pre[v]=u; u=v; aug=min(aug,e[i].w); if(v==vt) { flow+=aug; for(u=pre[v]; v!=vs; v=u,u=pre[u]) { e[cur[u]].w-=aug; e[cur[u]^1].w+=aug; } aug=inf; } break; } } if(flag)continue; int minlevel=NV; for(int i=head[u]; i!=-1; i=e[i].next) { int v=e[i].v; if(e[i].w&&level[v]<minlevel) { minlevel=level[v]; cur[u]=i; } } if(--gap[level[u]]==0)break; level[u]=minlevel+1; gap[level[u]]++; u=pre[u]; } return flow; } /**************************SAP**********************/ int x,y; void build() { vs=read();vt=read()+n;NV=2*n+1; for(int i=1;i<=n;i++) { x=read(); addedge(i,i+n,x); addedge(i+n,i,x); } for(int i=1;i<=m;i++) { x=read();y=read(); addedge(x+n,y,inf); addedge(y+n,x,inf); } } int main() { while(scanf("%d%d",&n,&m)>0) { init(); build(); printf("%d\n",SAP()); } }
时间: 2024-10-20 12:42:04