建图想了好久,想到了一种不需要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 连接到最后一个!!同时,把消负圈转换为最小费最大流,完美!哥服了!!总结,有些时候只要再多想想就会有更好的方法!
#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;
}