什么是前向星呢?
我们在存一张图时,常用的方法有邻接表,邻接矩阵等。但图论的题的顶点数往往达到104级别或以上,这就意味着我们不能用邻接矩阵来存储,而邻接表也只能开动态数组,非常耗时。因此我们引入前向星。
在图中,我们往往会建立点集数组,但同样,我们也可以建立边集数组。保存每一条边的两个端点编号和边权即可。然后我们以起始端点为第一关键字,指向端点为第二关键字排序,这样,以同一个节点起始的边就被放在一起了。所谓前向星就是指建立一个边集的索引,包括起始端点i在排序后的边集数组中首次出现的位置head[i]和以i为起始端点的边的数目len[i],这样,我们再访问时,就可以像邻接表一样访问了。
那什么是链式前向星呢?
类比链表,链式前向星是不需要排序的,我们维护这样的一个边集数组:
1 struct Edge{ 2 int to;//该边指向的节点 3 int value;//边权 4 int next;//起始端点相同的下一条边的编号 5 }edge[MAXM];
以及索引目录head[i](起始端点为i的第一条边,初始化为-1)
以下面最大流的前置重贴标签算法为例:
1 #include<iostream> 2 #include<iomanip> 3 #include<ctime> 4 #include<climits> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<cstring> 9 #include<cstdio> 10 #include<cstdlib> 11 #include<map> 12 using namespace std; 13 typedef unsigned long long LL; 14 #define rep(i,a,b) for(int i=a;i<=b;i++) 15 #define dep(i,a,b) for(int i=a;i>=b;i--) 16 inline int read(){ 17 int x=0;char ch=getchar(); 18 while(ch<'0'||ch>'9'){ 19 ch=getchar(); 20 } 21 while(ch>='0'&&ch<='9'){ 22 x=x*10+ch-'0'; 23 ch=getchar(); 24 } 25 return x; 26 } 27 28 const int MAXN=10001,MAXM=100001; 29 int to[MAXM],next[MAXM],value[MAXM];//链式前向星的三个要素 30 int head[MAXN],h[MAXN]={0},e[MAXN],cnt=0; 31 void _insert(int u,int v,int w){//加边 32 to[cnt]=v; 33 value[cnt]=w; 34 next[cnt]=head[u]; 35 head[u]=cnt++; 36 to[cnt]=u;//构建反向边(正反向边可以通过异或1得到) 37 value[cnt]=0; 38 next[cnt]=head[v]; 39 head[v]=cnt++; 40 } 41 int main(){ 42 int n=read(),m=read(),s=read(),t=read(); 43 memset(head,-1,sizeof(head)); 44 rep(i,1,m){ 45 int u=read(),v=read(),w=read(); 46 _insert(u,v,w); 47 } 48 h[s]=n; 49 e[s]=INT_MAX; 50 int ans=0,f; 51 queue<int>q; 52 for(int i=head[s];i!=-1;i=next[i]){//链式前向星标准访问循环 53 if(f=value[i]){ 54 value[i^1]=f; 55 value[i]=0; 56 e[s]-=f; 57 e[to[i]]=f; 58 if(to[i]==t)ans+=f;else q.push(to[i]); 59 } 60 } 61 while(!q.empty()){ 62 int u=q.front();q.pop(); 63 while(e[u]){ 64 int MIN=INT_MAX; 65 for(int i=head[u];i!=-1;i=next[i]){ 66 if(!value[i]||h[u]>h[to[i]]+1)continue; 67 if(h[u]==h[to[i]]+1){ 68 int f=min(value[i],e[u]); 69 e[u]-=f; 70 e[to[i]]+=f; 71 value[i]-=f; 72 value[i^1]+=f; 73 if(to[i]==t)ans+=f; 74 else if(to[i]!=s)q.push(to[i]); 75 } 76 else MIN=min(MIN,h[to[i]]); 77 } 78 if(e[u])h[u]=MIN+1; 79 } 80 } 81 cout<<ans<<endl; 82 return 0; 83 }