poj/pku 3680(最小费用最大流)
来源:互联网 发布:程序员怎么学 编辑:程序博客网 时间:2024/05/21 10:10
题目链接:http://poj.org/problem?id=3680
题意描述:给你n(n<=200)个区间,每个区间有一个权值,且每个区间的实数点最多只能访问k次,现在让你选择区间使得所选权值和最大
分析:该题是最大费用最大流,k可以看成是容量限制,刚开始这样想,将给出的每个区间看成一个点,然后将区间(i,i+1)i从0一直取到最大看成一些点,那么源点连接每个给出区间点,自己创造的区间点连接汇点,每个区间点都对应一些自己创造的区间点,但是这样做,不能正确的确定边的容量和费用,所以这样是解不出来的,无赖只好百度了一下,网上的建图方法经典至极啊,是将区间看成一条边而我只停留在将区间看成点的程度上,将区间看成边,那么对于这样的区间(i,i+1)那么他们最多允许流过k次,费用设为0,那么对给出区间的区间,这样的边就可以流过的流量设为1,表示只能选择一次,费用自然是区间的权值,现在这里给出建图的方法:建图之前可以将区间点离散化一下,这样可以减少些点,使得点最多不超过402个,那么我们建立源点和汇点,源点连接第一个点容量为k,费用为0,最后一个点连接汇点费用为0,容量为k,之间相邻的点相连,费用为0,容量为k,此处建图就体现了区间中所有的点最多只能流过k次,即最多只能被覆盖k次,之后对于给出的区间,我们连接区间的两个端点,容量为1,如果求最小费用则费用这里取反,否则为正!假设我们求最大费用最大流,我们每次都找源点到汇点的费用最长路,且每次找出一条路径都会将其经过的区间覆盖一次,如果不存在增广路则意味着不能在继续选区间啦!
代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int N=410;const int E=20000;const int inf=0x3fffffff;struct node{ int x, y,nxt,c,w;}edge[E];int head[N],e;int src,sin;struct node1{ int x, y,c;}a[N/2];int b[N];void addedge(int x,int y, int w, int c){ edge[e].x=x; edge[e].y=y; edge[e].w=w; edge[e].c=c; edge[e].nxt=head[x]; head[x]=e++; edge[e].x=y; edge[e].y=x; edge[e].w=0; edge[e].c=-c; edge[e].nxt=head[y]; head[y]=e++;}int find(int x,int high){ int low=1; while(low<=high) { int mid=(low+high)>>1; if(b[mid]==x) return mid; if(b[mid]<x) low=mid+1; else high=mid-1; }}int dis[N],que[N],pre[N];int Cost,Flow;bool isque[N];void mincmaxf(){ Cost=0;Flow=0;int u,v,i; while(1) { int f=0,r=1; for(i=src;i<=sin;i++) { dis[i]=inf; isque[i]=false; } dis[src]=0; que[0]=src; isque[src]=true; while(f!=r) { u=que[f]; f=(f+1)%N; for(i=head[u];i!=-1;i=edge[i].nxt) { v=edge[i].y; if(dis[v]>dis[u]+edge[i].c&&edge[i].w) { dis[v]=dis[u]+edge[i].c; pre[v]=i; if(!isque[v]) { que[r]=v; r=(r+1)%N; isque[v]=true; } } } isque[u]=false; } if(dis[sin]==inf)break; int p,min=inf; for(u=sin;u!=src;u=edge[pre[u]].x) { p=pre[u]; if(min>edge[p].w) min=edge[p].w; } Flow+=min; Cost+=min*dis[sin]; for(u=sin;u!=src;u=edge[pre[u]].x) { p=pre[u]; edge[p].w-=min; edge[p^1].w+=min; } }}int main (){ int t,n,k,i,j,x,y,c; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); memset(head,-1,sizeof(head)); e=0; for(i=1;i<=n;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c); b[i*2-1]=a[i].x; b[i*2]=a[i].y; } sort(b+1,b+2*n+1); for(i=2,j=2;i<=2*n;i++) if(b[i]!=b[i-1]) b[j++]=b[i]; sin=j;src=0; for(i=0;i<j;i++) addedge(i,i+1,k,0); for(i=1;i<=n;i++) { x=find(a[i].x,j-1); y=find(a[i].y,j-1); if(x>y)swap(x,y); addedge(x,y,1,-a[i].c); } mincmaxf(); printf("%d\n",-Cost); } return 0;}
- poj/pku 3680(最小费用最大流)
- pku 2516(最小费用最大流)
- POJ 3680 最小费用最大流
- poj 3680(最小费用最大流)
- POJ 3680 最小费用最大流
- poj 3680 Intervals (最小费用最大流)
- POJ 3680 最小费用最大流
- POJ 3680 最小费用最大流
- Intervals poj 3680 最小费用最大流
- pku 2195 Going Home(最小费用最大流)
- pku 2516 Minimum Cost(最小费用最大流)
- hdu 1533 && pku 2195 最小费用最大流
- POJ 3680 Intervals (最小费用最大流+离散化)
- Intervals (poj 3680 离散化+最小费用最大流)
- POJ 3680 <离散化+最小费用最大流模版>
- poj 2516 最小费用最大流
- 【最小费用最大流】POJ 2516【unsolved】
- 【最小费用最大流】POJ 2195
- iOS编程--Xcode使用指南1--Xcode菜单介绍--Xcode
- 矩阵理解(转)
- OpenCV命名规则
- 给年轻程序员的几句话
- TCP/IP网络协议学习笔记之以太网
- poj/pku 3680(最小费用最大流)
- css 针对IE的新方法
- C/C++ Standard Predefined Macros
- 80x86寄存器
- Hibernate-Criteria/DetachedCriteria 详解
- IE浏览器提交数据的编码方式
- javax.servlet.servletexception: cannot find actionmappings or actionformbeans collection
- MSM平台上的AMSS
- 键盘记录及自动发送VC++实现