poj 3680 Intervals 经典的建图!
2012-02-18 21:33
369 查看
建图想了好久,想到了一种不需要s和t的建图方法,先离散化,具体建法是 i + 1 连 i ,正容量是 k ,逆容量是0 ,费用是0,然后根据区间的限制,连接 ai 和 bi (都是离散化后的数据),正向容量是 1,逆向是0,正费用是 -w,逆费用是 w(把正向费用和逆向费用互换求最大费就变成求最小费了),这样就不需要 s
点和 t 点,求最大费,这种图求最大费的方法就是消负环了;可是消负环的代码很难写,而且复杂度很高,一般都是超时的,所以我还是放弃了这种消负环的建图方法;然后看了下discuss,牛逼!!!真tm牛逼!!原来这种建法可以改进!!!建图方法 ai 连 bi 不变,i+1 连 i 变成了 i 连 i+1 ,容量是 inf ,我当时疑惑为什么是 inf 啊??!!如果每条边都是 inf 那么最后每条边都要小于 k 的条件如何限制?!!答案令我惊讶,居然添加一个 s 连接到 1,添加一个 t 连接到最后一个!!同时,把消负圈转换为最小费最大流,完美!哥服了!!总结,有些时候只要再多想想就会有更好的方法!
点和 t 点,求最大费,这种图求最大费的方法就是消负环了;可是消负环的代码很难写,而且复杂度很高,一般都是超时的,所以我还是放弃了这种消负环的建图方法;然后看了下discuss,牛逼!!!真tm牛逼!!原来这种建法可以改进!!!建图方法 ai 连 bi 不变,i+1 连 i 变成了 i 连 i+1 ,容量是 inf ,我当时疑惑为什么是 inf 啊??!!如果每条边都是 inf 那么最后每条边都要小于 k 的条件如何限制?!!答案令我惊讶,居然添加一个 s 连接到 1,添加一个 t 连接到最后一个!!同时,把消负圈转换为最小费最大流,完美!哥服了!!总结,有些时候只要再多想想就会有更好的方法!
#include<iostream> #include<vector> #include<cstring> #include<string> #include<iomanip> #include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> #include<stack> #include<map> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 431; const int end = 430; struct zz { int from; int to; int c; int cost; int id; }zx,tz; int n,k,T,tot; int a[maxn]; int b[maxn]; int w[maxn]; int fx[maxn]; map<int,int>m; vector<int>v; vector<int>vs; vector<zz>g[maxn]; queue<int>q; int way[maxn]; bool inq[maxn]; int backid[maxn]; inline void link(int now,int to,int c,int cost,int bc,int bcost) { zx.from = now; zx.to = to; zx.cost = cost; zx.c = c; zx.id = g[to].size(); g[now].push_back(zx); swap(zx.from,zx.to); zx.c = bc; zx.cost = bcost; zx.id = g[now].size() - 1; g[zx.from].push_back(zx); return ; } bool spfa() { while(!q.empty()) { q.pop(); } for(int i=1;i<=tot;i++) { way[i] = inf; } way[end] = inf; way[0] = 0; memset(inq,false,sizeof(inq)); memset(backid,-1,sizeof(backid)); inq[0] = true; q.push(0); int now,to; int temp; int cost; int id; while(!q.empty()) { now = q.front(); q.pop(); for(int i=0;i<g[now].size();i++) { if(g[now][i].c > 0) { to = g[now][i].to; id = g[now][i].id; cost = g[now][i].cost; temp = way[now] + cost; if(temp < way[to]) { way[to] = temp; backid[to] = id; if(!inq[to]) { q.push(to); inq[to] = true; } } } } inq[now] = false; } int nowid; temp = end; int minflow = inf; while(backid[temp] != -1) { id = backid[temp]; now = g[temp][id].to; nowid = g[temp][id].id; minflow = min(minflow , g[now][nowid].c); temp = now; } temp = end; while(backid[temp] != -1) { id = backid[temp]; now = g[temp][id].to; nowid = g[temp][id].id; g[now][nowid].c -= minflow; g[temp][id].c += minflow; temp = now; } if(way[end]!=inf) { return true; } else { return false; } } int EK() { int ans=0; while(true) { spfa(); if(way[end]<0) { ans += way[end]; } else { break; } } return -ans; } int main() { cin>>T; while(T--) { // cin>>n>>k; scanf("%d%d",&n,&k); v.clear(); v.push_back(0); m.clear(); vs.clear(); for(int i=1;i<=n;i++) { // cin>>a[i]>>b[i]>>w[i]; scanf("%d%d%d",&a[i],&b[i],&w[i]); vs.push_back(a[i]); vs.push_back(b[i]); } sort(vs.begin(),vs.end()); int temp = vs[0]; v.push_back(temp); for(int i=1;i<vs.size();i++) { if(vs[i] != temp) { temp = vs[i]; v.push_back(temp); } else { continue; } } for(int i = 1; i < v.size(); i++) { m[v[i]] = i; // ÀëÉ¢»¯ } tot = v.size() - 1; for(int i=0;i<maxn;i++) { g[i].clear(); } link(0,1,k,0,0,0); link(tot,end,k,0,0,0); for(int i=1;i<tot;i++) { link(i,i+1,inf,0,0,0); } for(int i=1;i<=n;i++) { link(m[a[i]],m[b[i]],1,-w[i],0,w[i]); } printf("%d\n",EK()); } return 0; }
相关文章推荐
- POJ 3680 Intervals (费用流经典构图题)
- POJ 3680 Intervals(经典费用流)
- POJ 3680 Intervals(区间k覆盖问题)
- 2014湘潭全国邀请赛I题 Intervals /POJ 3680 / 在限制次数下取有权区间使权最大/小问题(费用流)
- POJ3680——Intervals(费用流)
- POJ-3680:Intervals (费用流)
- poj 3680 Intervals(最大费用流+离散化)
- POJ 3680 Intervals
- poj 3680 Intervals(离散化+费用流)
- poj 3680 Intervals 最大费用流
- 【POJ】 3680 Intervals 离散 + 费用流
- poj 3680 intervals
- poj3680 Intervals 区间k覆盖问题 最小费用最大流 建图巧妙
- POJ 3680 Intervals
- POJ 3680 Intervals 神奇的构图
- Intervals (poj 3680 离散化+最小费用最大流)
- poj 3680 Intervals
- POJ 3680 Intervals
- poj 3680 Intervals【最小费用最大流】
- POJ 3680 Intervals (最小费用最大流+离散化)