传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1930
显然豆豆相不相交一个样
显然暴力建边会挂
那么要减少边数
如果一个点可以通过一个点作中介到达后一个点,那么前后两个点不连边
最后的建图是
s->ss cap=2 cost=0
ss->in cap=1 cost=0
in -> out cap=1 cost=1
in->out cap=1 cost=0
out->tt cap=1 cost=0
tt->t cap=2 cost=0
Code:
#include<bits/stdc++.h>
#define in(i) (i<<1)
#define out(i) (i<<1|1)
using namespace std;
const int maxn=4020;
int n,s,t;
struct edge{
int u,v,cap,flow,cost;
edge(int _u=0,int _v=0,int _cap=0,int _flow=0,int _cost=0):
u(_u),v(_v),cap(_cap),flow(_flow),cost(_cost){}
};
vector<edge>edges;
vector<int>G[maxn];
int pre[maxn],a[maxn],d[maxn],vis[maxn],cost;
void add(int u,int v,int cap,int cost){
edges.push_back(edge(u,v,cap,0,cost));
G[u].push_back(edges.size()-1);
edges.push_back(edge(v,u,0,0,-cost));
G[v].push_back(edges.size()-1);
}
bool spfa(){
queue<int>q;
q.push(s);
memset(d,0xaf,sizeof d);int B=d[0];d[s]=0;a[s]=INT_MAX;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=0;i<G[u].size();i++){
edge e=edges[G[u][i]];
if(e.cap>e.flow&&d[e.v]<d[u]+e.cost){
d[e.v]=d[u]+e.cost;
pre[e.v]=G[u][i];
a[e.v]=min(a[u],e.cap-e.flow);
if(!vis[e.v]){
vis[e.v]=1;
q.push(e.v);
}
}
}
}
if(d[t]==B)return false;
cost+=d[t]*a[t];
for(int u=t;u!=s;u=edges[pre[u]].u){
edges[pre[u]].flow+=a[t];
edges[pre[u]^1].flow-=a[t];
}return true;
}
pair<int,int>p[maxn];
int main(){
scanf("%d",&n);s=0;t=(n<<1|1)+1;int ss=(n<<1|1)+2,tt=(n<<1|1)+3;
for(int i=1;i<=n;i++)scanf("%d%d",&p[i].first,&p[i].second);
sort(p+1,p+1+n);
add(s,ss,2,0);add(tt,t,2,0);
for(int i=1;i<=n;i++){
add(ss,in(i),1,0);
add(in(i),out(i),1,1);
add(in(i),out(i),1,0);
add(out(i),tt,1,0);
}
for(int i=1;i<=n;i++){
int miny=INT_MAX;
for(int j=i+1;j<=n;j++){
if(p[j].second>=p[i].second&&p[j].second<miny)
add(out(i),in(j),2,0),miny=min(miny,p[j].second);
}
}int deb=0;
if(deb)
for(int i=0;i<edges.size();i++)if(i%2==0)
printf("%d->%d cap:%d cost:%d\n",edges[i].u,edges[i].v,edges[i].cap,edges[i].cost);
while(spfa());
cout<<cost<<endl;
return 0;
}