标签:sgu
题目大意:
给你一个图,n(点数),m(边数),l,和每个点上的标号h,h表示到源点的最短路,h=1表示是源点,h=l表示是汇点,显然是一个层次图,然后要你求最大流。
解题思路:
首先我们注意一下数据范围,然后我就怂了,本来看到题目觉得就是分分钟dinic上去秒掉的,但是我还是too naive,所以我只能滚粗去学预流推进了。。。。。。。
由于预流推进很难讲,所以请大家自己去查阅资料吧。
我们假设大家都会了预流推进,但是我自己写的最高标号预流推进居然超时了,然后我就各种丧心病狂的优化,我来介绍一点优化吧!
优化1:输出优化,把所有要输出的都转成字符串,然后用putchar或者puts
优化2:我们不需要进行BFS或着DFS,只需要用输入的h就行了
优化3:听说sgu开了O2对吧,inline函数搞起!!
优化4:我们应该尽量开小空间,因为空间小速度快啊!!!
优化5:用hash表示这个数是否在优先队列中,以免重复进队!!
AC代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)>(b)?(b):(a)) using namespace std; short h[1510]={0}; struct list { int x; int H; bool friend operator < (const list &a,const list &b) { return a.H<b.H; } }; struct bian_ { short num; int next; }b[600010]={{0,0}}; int First[1510]={0}; int n,m,l; int s,t; priority_queue <list> dui; int flow[1510][1510]={{0}}; int yl[1510]={0}; short bian[300010][2]={{0}}; int ss=0; bool hash[1510]={0}; char ans[100000]="\0"; int ansp; inline void Add(int i,int j,int k) { b[k].num=j; b[k].next=First[i]; First[i]=k; return; } inline void get_ch(int k) { char help[10]="\0"; int i; if(k==0) ans[++ansp]='0'; else { for(i=0;k!=0;k/=10) help[++i]=k%10+'0'; for(;i>0;--i) ans[++ansp]=help[i]; } ans[++ansp]='\n'; return; } int main() { scanf("%d%d%d",&n,&m,&l); for(register int i=1;i<=n;++i) { scanf("%d",&h[i]); if(h[i]==1) s=i; if(h[i]==l) t=i; h[i]=l+1-h[i]; } for(register int i=1;i<=m;++i) { scanf("%d%d",&bian[i][0],&bian[i][1]); scanf("%d",&flow[bian[i][0]][bian[i][1]]); Add(bian[i][0],bian[i][1],i*2-1); Add(bian[i][1],bian[i][0],i*2); } h[s]=l+1; yl[s]=2e9; yl[t]=-2e9; struct list q; q.x=s; q.H=h[s]; dui.push(q); hash[s]=1; ++ss; for(;ss!=0;) { q=dui.top(); dui.pop(); --ss; int u=q.x; hash[u]=0; for(register int i=First[u];i!=0;i=b[i].next) { int v=b[i].num; if(yl[u]==0) break; int p=MIN(flow[u][v],yl[u]); if(p>0 && (u==s || h[u]==h[v]+1)) { flow[u][v]-=p; flow[v][u]+=p; yl[u]-=p; yl[v]+=p; if(v!=s && v!=t && hash[v]==0) { q.x=v; q.H=h[v]; dui.push(q); ++ss; hash[v]=1; } } } if(u!=s && u!=t && yl[u]>0) { ++h[u]; q.x=u; q.H=h[u]; dui.push(q); ++ss; hash[u]=1; } } for(register int i=1;i<=m;++i) get_ch(flow[bian[i][1]][bian[i][0]]); for(register int i=1;i<=ansp;++i) putchar(ans[i]); return 0; }
标签:sgu
原文地址:http://blog.csdn.net/qq_21995319/article/details/42641233