原始对偶费用流
用 \(Dijkstra\) 代替 \(SPFA\)。Link,但是这篇博客的代码上来就跑 \(Dijkstra\),复杂度可能会被卡成指数。
\(\text{Problem}:\)Interval Graph
\(\text{Solution}:\)
满足题意的充要条件:每个点至多被两个区间覆盖。
\(i\rightarrow i+1\) 连一条流量为 \(2\),费用为 \(0\) 的边。
\(l\rightarrow r+1\) 连一条流量为 \(1\),费用为 \(-w\) 的边。
然后跑最小费用最大流。此题需要用 \(Primal-dual\) 优化。
但是第一次跑 \(Dijkstra\) 的时候有负权,所以先把边权都变成正的,再跑 \(Dijkstra\)。
\(\text{Code}:\)
#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
using namespace std; const int N=500010, INF=1e18;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int n,Ans;
struct Link { int x,y,z; }g[N];
int S,T,dis[N],pre[N],H[N],book[N];
int head[N],maxE,cur[N]; struct Edge { int nxt,to,rdis,cost; }e[N<<2];
inline void Add(int u,int v,int w1,int w2)
{
e[maxE].nxt=head[u];
head[u]=maxE;
e[maxE].to=v;
e[maxE].rdis=w1;
e[maxE].cost=w2;
maxE++;
}
struct Node { int x,w; inline bool operator < (const Node& a) const { return w>a.w; } };
inline bool Dijk()
{
priority_queue<Node> Q;
memset(dis,0x3f,sizeof(dis));
memset(book,0,sizeof(book));
memset(pre,-1,sizeof(pre));
dis[S]=0, Q.push((Node){S,0});
while(!Q.empty())
{
Node now=Q.top(); Q.pop();
int x=now.x;
if(book[x]) continue;
book[x]=1;
for(ri int i=head[x];~i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].rdis>0&&dis[v]>dis[x]+e[i].cost+H[x]-H[v])
{
dis[v]=dis[x]+e[i].cost+H[x]-H[v];
pre[v]=i;
Q.push((Node){v,dis[v]});
}
}
}
return ~pre[T];
}
signed main()
{
memset(head,-1,sizeof(head));
n=read();
for(ri int i=1;i<=n;i++)
{
int x,y,z;
x=read(), y=read(), z=read();
T=max(T,y+1);
g[i]=(Link){x,y,z};
}
for(ri int i=0;i<T;i++) Add(i,i+1,2,0), Add(i+1,i,0,0);
for(ri int i=1;i<=n;i++) Add(g[i].x,g[i].y+1,1,-g[i].z), Add(g[i].y+1,g[i].x,0,g[i].z);
memset(pre,-1,sizeof(pre));
memset(dis,0x3f,sizeof(dis));
dis[S]=0;
for(ri int x=0;x<=T;x++)
for(ri int i=head[x];~i;i=e[i].nxt)
{
int v=e[i].to;
if(e[i].rdis>0&&dis[v]>dis[x]+e[i].cost)
dis[v]=dis[x]+e[i].cost, pre[v]=i;
}
if(pre[T]==-1) return puts("0")&0;
for(ri int i=0;i<=T;i++) if(dis[i]<INF) H[i]+=dis[i];
int res=INF;
for(ri int i=T;i!=S;i=e[pre[i]^1].to) res=min(res,e[pre[i]].rdis);
for(ri int i=T;i!=S;i=e[pre[i]^1].to)
{
e[pre[i]].rdis-=res;
e[pre[i]^1].rdis+=res;
}
Ans+=res*H[T];
while(Dijk())
{
for(ri int i=0;i<=T;i++) if(dis[i]<INF) H[i]+=dis[i];
int res=INF;
for(ri int i=T;i!=S;i=e[pre[i]^1].to) res=min(res,e[pre[i]].rdis);
for(ri int i=T;i!=S;i=e[pre[i]^1].to)
{
e[pre[i]].rdis-=res;
e[pre[i]^1].rdis+=res;
}
Ans+=res*H[T];
}
printf("%lld\n",-Ans);
return 0;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。