poj 3921 (控制费用的 最小割)
来源:互联网 发布:微信群淘宝客机器人 编辑:程序博客网 时间:2024/04/30 14:00
题意:
有N个据点..敌人要从1号据点往N号据点去..有些据点间存在直接路径..敌人走一条路径都为一个单位时间...而咱可以摧毁一个据点..这么做就让与这个据点相连的路径全部作废..问为了防止敌人在K单位时间内到达N点..至少要摧毁几个据点..注意的是1、N号据点是不能摧毁的...并且1与N没有直接的路径..
拆最少的点,拆点后,就转换为删最少的边 ,问题转换成最小割; 如果没有源点到汇点路径不超过k这个限制,哪就是裸的最小割了 ; 但,我们只许在求费用流的时候,当源点到汇点的费用大于k时(dist[t]>k),就退出,此时的最大流就是最小割了。
建图:对每个点i拆点为i和i+n,令源点s=1,汇点t=2*n。增加弧(1, 1+n) ,(n, 2*n) 容量都为INF,费用都为0; 而对于非源汇点, 增加弧(i, i+n)容量为1, 费用为0。若原图中存在边(u, v),增加弧(u+n, v), 容量为inf,费用为1(边权)。题目要求删点后点1到点n不存在距离大于k的路径,则对该网络求费用流,在费用大于k的时候停止(费用=边权=1).答案便是此时的最大流
#include<cstdio>#include<cstring>#include<map>#include<vector>#include<cmath>#include<cstdlib>#include<stack>#include<queue>#include <iomanip>#include<iostream>#include<algorithm>using namespace std ;const int N=200;const int M=10000;const int inf=1<<30 ;struct node{int u,v,c,cost,next;}edge[M];int head[N],dist[N],pre[N],pp[N],vist[N];int top ,n,m,k;void add(int u ,int v,int c,int cost) { edge[top].u=u; edge[top].v=v; edge[top].c=c; edge[top].cost=cost; edge[top].next=head[u]; head[u]=top++; edge[top].u=v; edge[top].v=u; edge[top].c=0; edge[top].cost=-cost; edge[top].next=head[v]; head[v]=top++; } int SPFA(int s,int t) { int u , v ; memset(vist,0,sizeof(vist)); memset(pre,-1,sizeof(pre)); for(int i = 0 ; i <= t ; i++) dist[i]=inf ; vist[s]=1;dist[s]=0;pre[s]=s; queue<int>q; q.push(s); while(!q.empty()) { u=q.front(); q.pop(); vist[u]=0; for(int i =head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(edge[i].c && dist[v] > dist[u]+edge[i].cost) { dist[v] = dist[u]+edge[i].cost ; pre[v]=u; pp[v]=i; if(!vist[v]); { vist[v]=1; q.push(v); } } } } if(dist[t]==inf) return 0; return 1 ; } int MFMC(int s,int t) { int mincost=0,flow=0,minflow ,ans=0; while(SPFA(s,t)) { if(dist[t] > k) break; minflow=inf; for(int i=t;i!=s;i=pre[i]) minflow=min(minflow,edge[pp[i]].c); for(int i=t;i!=s;i=pre[i]) { edge[pp[i]].c -= minflow; edge[pp[i]^1].c += minflow; } flow += minflow; mincost += dist[t]*minflow ; } return flow ; } int main(){ int a,b; while(~scanf("%d%d%d",&n,&m,&k)) { if((n+m+k)==0) break; top = 0; memset(head,-1,sizeof(head)); int s = 1,t=2*n ; for(int i = 1 ; i <= m ; i++) { scanf("%d%d",&a,&b); add(a+n,b,1,1); } for(int i = 2 ; i < n ;i++) add(i,i+n,1,0); add(1,1+n,inf,0);add(n,n+n,inf,0); int ans = MFMC(s,t); printf("%d\n",ans); }return 0;}
0 0
- poj 3921 (控制费用的 最小割)
- POJ 1815 (最小割的点集)
- poj 3084(最小割。。。。。)
- poj 3469 最小割
- poj 2914 最小割
- poj 3308 最小割
- poj 3469 最小割
- POJ 3308 最小割
- POJ 3469 最小割
- POJ 3308 最小割
- poj 3084 最小割
- POJ 3469 最小割
- 最小割-poj-2914
- poj 2125(最小割)
- poj 3084(最小割)
- poj 3469 最小割
- poj 3084 最小割
- POJ 3469 最小割
- 无聊的黑叔
- [Django]models中定义的choices 字典在页面中显示值
- [无限互联]学员作品:旅游软件“在路上”IOS客户端
- SDUT 1068-Number Steps(数学:直线)
- poj2406--Power Strings(KMP求最小循环节)
- poj 3921 (控制费用的 最小割)
- Struts 2的工作流程
- html使用列表 以及div的布局和table的布局
- HDOJ题目1505 City Game(动态规划)
- Java 学习 第三章 Java核心-继承与多态
- ANDROID L——Material Design详解(视图和阴影)
- struts2的优点
- poj1961--Period(KMP求最小循环节)
- 一个人的旅行 hdu 2066