题解:
相邻的建边
每一段建边
然后见一个原点,汇点
代码:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=100005; int b[N],T,c[N],fi[N],n,t,cas,m,x,mp[N],k,a[N]; int y,z,f[N],ne[N],num,zz[N],fl[N],gp[N],dist[N],pre[N],sl[N]; void jb(int x,int y,int z,int s) { ne[num]=fi[x]; fi[x]=num; zz[num]=y; sl[num]=z; fl[num++]=s; ne[num]=fi[y]; fi[y]=num; zz[num]=x; sl[num]=0; fl[num++]=-s; } int spfa() { memset(dist,0x3f,sizeof dist); memset(pre,-1,sizeof pre); memset(gp,0,sizeof gp); memset(f,0,sizeof f); queue<int > Q; Q.push(1); dist[1]=0; while (!Q.empty()) { int now=Q.front(); Q.pop(); f[now]=0; for (int i=fi[now];i!=-1;i=ne[i]) if (sl[i]>0) { int t=zz[i]; if (dist[t]>dist[now]+fl[i]) { dist[t]=dist[now]+fl[i]; pre[t]=now; gp[t]=i; if (!f[t]) { f[t]=1; Q.push(t); } } } } if (pre[n+2]==-1)return 1; return 0; } void Max_flow() { int cost=0,flow=0; while (!spfa()) { int f=1e9; for (int i=n+2;i>1;i=pre[i]) f=min(f,sl[gp[i]]); cost+=f; flow+=dist[n+2]*f; for (int i=n+2;i>1;i=pre[i]) { sl[gp[i]]-=f; sl[gp[i]^1]+=f; } } printf("%d ",-flow); } void init() { // printf("Instance #%d: ",++cas); num=0; memset(mp,0,sizeof mp); memset(fi,-1,sizeof fi); } void doit() { scanf("%d%d",&n,&k); for (int i=1;i<=n;i++) { scanf("%d%d%d",&a[i],&b[i],&c[i]); f[i*2-1]=a[i];f[i*2]=b[i]; } sort(f+1,f+n+n+1); mp[f[1]]=1; int tot=1; for (int i=2;i<=2*n;i++) if (f[i]!=f[tot])mp[f[i]]=++tot,f[tot]=f[i]; for (int i=2;i<=tot;i++)jb(i,i+1,k,0); for (int i=1;i<=n;i++)jb(mp[a[i]],mp[b[i]],1,-c[i]); jb(1,2,k,0);jb(tot+1,tot+2,k,0); n=tot; Max_flow(); } int main() { scanf("%d",&T); while (T--) { init(); doit(); } }