1 5 1 1 2 3 3 2 4 3 5 1
4
Accepted | 5406 | 296MS | 2204K | 3031 B | G++ |
http://blog.csdn.net/mxymxy1994mxy/article/details/47818397
这篇博客中提供的思路大约边都为原来的50分之一了,优化好厉害。学习了。
http://blog.csdn.net/l_ecry/article/details/47830927
用栈优化时间快了4倍左右!!也是6666
对于spfa的优化,对于队列而言确实能够有不少的优化。如下:
http://www.cnblogs.com/cj695/archive/2012/07/27/2611215.html
对于这题建图:
建立s,t, 把i点拆为i,i+n,建立虚拟节点限制流量s1,
s->s1 容量2,
s->i, i->t,容量1,
除了i->i+n的费用为-1,其他边费用都为0
对h从小到大排序,d从大到小排序,
边优化:对于a+n->x, a+n->y 如果x >= y 那么a+n不需要对y连边,因为通过x也可以到达y。
这就是博客1中单调块的思想。但是,会出现单调块的入口被占据的情况,
那么建边的同时建立一条a->x的路径,表示路过a点,直接访问a能到达的点。
费用流好久没用了,好神奇。!!!!
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define maxn 2017 #define maxm 200000 #define inf 10000000 using namespace std; int head[maxn],tail; int queue[maxn],pre[maxn],flag[maxn]; int dist[maxn],maxFlow[maxn]; struct Edge{ int v,u,next,cost,w; Edge(){}//费用,权值 Edge(int u,int v,int next,int cost,int w):u(u),v(v),next(next),cost(cost),w(w){} } edge[maxm]; void add_edge(int u,int v,int cost,int w){ edge[tail] = Edge(u,v,head[u],cost,w); head[u] = tail++; edge[tail] = Edge(v,u,head[v],-cost,0); head[v] = tail++; } void init(){ memset(head,-1,sizeof(head)); tail=0; } int SPFA(int start,int end){ int i,u,v,front,rear; front = rear = 0; memset(flag,0,sizeof(flag)); memset(dist,0x1f,sizeof(dist)); memset(pre,-1,sizeof(pre)); dist[start] = 0, dist[end] = inf ,flag[start]=1; maxFlow[start] = inf, queue[rear++] = start; while(front != rear){//增广 u = queue[--rear]; //if(front >= maxn) front = 0; flag[u] = 0; for(i = head[u]; i!=-1;i=edge[i].next){ v=edge[i].v; if(edge[i].w&&dist[v]>dist[u]+edge[i].cost){ dist[v]=dist[u]+edge[i].cost; maxFlow[v]=min(edge[i].w,maxFlow[u]); pre[v]=i;//记录边下标 if(!flag[v]){ queue[rear++]=v; // if(rear>=maxn)rear=0; flag[v] =1; } } } } return dist[end] != inf; } //开始点,结束点 int MFMC(int start,int end){ int min_cost = 0,v; while(SPFA(start,end)){ v = end; while(pre[v]>=0){ edge[pre[v]].w-=maxFlow[end]; edge[pre[v]^1].w+=maxFlow[end]; v=edge[pre[v]].u; }//跟新费用 min_cost+=dist[end]*maxFlow[end]; } return min_cost; } struct Node{ int h,d; }; Node p[1001]; int comp(Node a,Node b){ if(a.h == b.h) return a.d > b.d; return a.h < b.h; } int main(){ int t,n,h,d; //freopen("1001.in","r",stdin); //freopen("1001x.out","w",stdout); scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i = 0 ;i < n; i++){ scanf("%d%d",&p[i].h,&p[i].d); } sort(p,p+n,comp); init(); int s1 = n*2, S = s1+1, T = S+1; for(int i = 0;i < n; i++){ add_edge(s1,i,0,2); add_edge(i+n,T,0,1); add_edge(i,i+n,-1,1); } add_edge(S,s1,0,2); for(int i = 0;i < n; i++){ int x = -10; for(int j = i+1;j < n; j++){ if(p[j].d <= p[i].d && p[j].d > x){ add_edge(i+n,j,0,1); add_edge(i,j,0,1); x = p[j].d; } } } int ans = 0; ans = MFMC(S,T); printf("%d\n",-ans); } return 0; }