[Vijos P1524]最小监视代价
Posted Mrsrz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Vijos P1524]最小监视代价相关的知识,希望对你有一定的参考价值。
题目大意:有一些点和一些边,每条边有一个监视代价。一个人从1号点出发,到达某些“传送点”可以逃生。但被监视的边就不能走了。要你用最小的监视代价使得那个人无法传送。
解题思路:求最小割。先建一个超级汇点$n+1$,把所有传送点连上这个超级汇点,然后根据“最小割=最大流”的定理,跑最大流即可。注意无向图。
以下为Dinic算法代码。
C++ Code:
#include<cstdio> #include<vector> #include<cstring> #include<queue> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f struct edges{ int to,cap,rev; edges(int t,int c,int r):to(t),cap(c),rev(r){} }; vector<edges>G[105]; int n,m,level[105],iter[105]; queue<int>q; inline void addedge(int from,int to,int cap){ G[from].push_back(edges(to,cap,G[to].size())); G[to].push_back(edges(from,cap,G[from].size()-1));//无向图,所以反向边也有容量 } void bfs(int s){ memset(level,-1,sizeof level); level[s]=0; q.push(s); while(!q.empty()){ int u=q.front();q.pop(); for(int i=0;i<G[u].size();++i){ edges& e=G[u][i]; if(level[e.to]<0&&e.cap>0){ level[e.to]=level[u]+1; q.push(e.to); } } } } int dfs(int u,int t,int f){ if(u==t)return f; for(int& i=iter[u];i<G[u].size();++i){ edges& e=G[u][i]; if(level[e.to]>level[u]&&e.cap>0){ int d=dfs(e.to,t,min(f,e.cap)); if(d){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int max_flow(int s,int t){ int flow=0; while(1){ bfs(s); if(level[t]<0)break; memset(iter,0,sizeof iter); int f; while(f=dfs(s,t,INF))flow+=f; } return flow; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ int from,to,cap; scanf("%d%d%d",&from,&to,&cap); addedge(from,to,cap); } int p; ++n; scanf("%d",&p); while(p--){ int x; scanf("%d",&x); addedge(x,n,INF); } printf("%d\n",max_flow(1,n)); return 0; }
以上是关于[Vijos P1524]最小监视代价的主要内容,如果未能解决你的问题,请参考以下文章