传送门: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; }