POJ 3680 Intervals (最大费用最大流)
2016-04-26 17:27
489 查看
大意:给定n,k分别代表n段线段,累加的线段不会超过k次。问最后所以的累加最大和是多少。
思路:最大费用最大流,刚上来建图弄错了。建成了原点与每个点都有流量为K,费用为0的边。这样显然是错的。那么就需要建源点到1点流量为k的边,同理cnt到ed点也有流量为k的边。就保证了不会超过k次。但是注意边和边之间的连线因为都是同一性质的点所以直接短点相连即可。(PS:1离散化 2.求解最大值,所以建图要用复权;并且不能够用map离散化,因为建的图并不是所以从小点到大点进行联通的)
思路:最大费用最大流,刚上来建图弄错了。建成了原点与每个点都有流量为K,费用为0的边。这样显然是错的。那么就需要建源点到1点流量为k的边,同理cnt到ed点也有流量为k的边。就保证了不会超过k次。但是注意边和边之间的连线因为都是同一性质的点所以直接短点相连即可。(PS:1离散化 2.求解最大值,所以建图要用复权;并且不能够用map离散化,因为建的图并不是所以从小点到大点进行联通的)
#include<map> #include<queue> #include<cmath> #include<vector> #include<cstdio> #include<stack> #include<iostream> #include<cstring> #include<algorithm> #define ll long long #define LL unsigned __int64 #define inf 0x3f3f3f3f #define eps 1e-8 using namespace std; int n,k,cnt,sum,head[100010*5],maxcost; const int N = 410; struct node{ int to,c,w,next; }q[1010*5]; int tmp1[2100],cur[2100],tmp2[2100],tmp3[2100],star,ed,f[2100*5],dis[2100]; bool vis[2010]; int tt[21000],mp[2100],ha[100010]; void bu(int a,int b,int w,int c){ q[sum].to = b; q[sum].w = w; q[sum].c = c; q[sum].next=head[a]; head[a] = sum++; q[sum].to = a; q[sum].w = 0; q[sum].c = -c; q[sum].next=head[b]; head[b] = sum++; } bool SPFA(){ memset(cur,-1,sizeof(cur)); memset(vis,false,sizeof(vis)); memset(dis,inf,sizeof(dis)); queue<int>Q; while(!Q.empty()) Q.pop(); Q.push(star); vis[star] = true; f[star] = inf; dis[star] = 0; while(!Q.empty()){ int u = Q.front();Q.pop(); vis[u] = false; for(int i = head[u];~i;i=q[i].next ){ int v = q[i].to; if(dis[v] > dis[u] + q[i].c&&q[i].w > 0){ dis[v] = dis[u] + q[i].c; cur[v] = i; f[v] = min(f[u],q[i].w); if(!vis[v]){ vis[v] = true; Q.push(v); } } } } return dis[ed] != inf; } int so(){ int ant = 0; for(int i = ed;i!=star;i=q[cur[i]^1 ].to){ q[cur[i] ].w -= 1; q[cur[i]^1 ].w += 1; ant += q[cur[i] ].c; } return ant; } int main(){ int m,i,j,cla,c; scanf("%d",&cla); while(cla--){ sum = 0;cnt = 0; memset(head,-1,sizeof(head)); scanf("%d%d",&n,&k); //mp.clear(); memset(ha,0,sizeof(ha)); for(i = 1;i <= n;++ i){ scanf("%d%d%d",&tmp1[i],&tmp2[i],&tmp3[i]); // if(!mp[tmp1[i] ]){ // mp[tmp1[i] ] = ++cnt; // } // if(!mp[tmp2[i] ]){ // mp[tmp2[i] ] = ++cnt; // } ha[tmp1[i] ] = ha[tmp2[i] ] = 1; } for(i = 1;i <= 100000;++ i) if(ha[i]) mp[i] = ++cnt; star = cnt+1; ed = cnt+2; for(i = 1;i < cnt;++ i) bu(i,i+1,k,0); bu(star,1,k,0); bu(cnt,ed,k,0); for(i = 1;i <= n;++ i){ bu(mp[tmp1[i]],mp[tmp2[i] ],1,-tmp3[i]); } int ans = 0; while(SPFA()) ans += so(); printf("%d\n",-ans); } return 0; }
相关文章推荐
- ACDream 1171 最大费用流,流量不一定最大
- HDU 4322 Candy 最大费用流
- WPF DataGrid绑定及列居中
- 第六次作业
- FIlter应用
- node.js---sails项目开发(5)---用户表的建立
- MS15-020漏洞测试
- 冲刺第四天
- LaTex技巧[22]:LaTex插图命令includegraphics参数详解
- SharePoint 2013 Foundation 报错: 试图调用服务应用程序时报告了失败: EndpointFailure 8313
- Table configuration with catalog null, schema orcl, and table ORDERS did not resolve to any tables
- int main(int argc, char **argv)中参数argc与argv的意义
- Spark组件之Spark Streaming学习3--结合SparkSQL的使用(wordCount)
- Nginx日志切割
- Java简繁转换ZHConverter
- notepad++编辑的json文件copy到myEclipse后中文乱码
- string stringBuffer stringBuilder 区别
- [No000085]C#反射Demo,通过类名(String)创建类实例,通过方法名(String)调用方法
- 详解C语言中条件判断语句if和switch的用法
- cf665e.cpp 01 trie树求抑或