网络流之最大流 poj 1459

差不多三天的时间过去了,学了一个网络流最大流。。

现在来总结一下。。。

先说一下之前那个ek的算法,说实话,这个算法本质上很好去理解,就是利用一个广搜不断的搜出所谓的增广路径。

View Code
 1 #include<iostream>
 2     #include<string.h>
 3     #include<queue>
 4     #define N 110
 5     using namespace std;
 6     int map[N][N];
 7     int n,np,nc,m,s,e,w; 
 8     int link[N],num[N],answer;
 9     char temp[20];
10     int bfs()
11     {
12         queue<int> q;
13         num[n]=0x7fffffff;
14         q.push(n);
15         for(int i=0;i<=n+1;i++)link[i]=-1;
16         while(!q.empty())
17         {
18             int cur=q.front();
19             q.pop();
20             if(cur==n+1)
21             {
22                answer+=num[n+1];
23                int from,now=n+1;
24                while(now!=n)
25                {
26                    from=link[now];
27                    map[from][now]-=num[n+1];
28                    map[now][from]+=num[n+1];
29                    now=from;
30                }
31                while(!q.empty())q.pop();
32                num[n]=0x7fffffff;
33                for(int i=0;i<=n+1;i++)link[i]=-1;
34                q.push(n);
35                continue;
36             }
37             for(int i=0;i<=n+1;i++)
38             {
39                if(map[cur][i]&&link[i]==-1)
40                {
41                    link[i]=cur;
42                    num[i]=num[cur]<map[cur][i]?num[cur]:map[cur][i];
43                    q.push(i);
44                }
45             }
46         }
47         return answer;  
48     }
49     int main()
50     {
51        while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
52        {
53               for(int i=0;i<=n+1;i++)
54               {
55                  for(int j=0;j<=n+1;j++)
56                  {
57                          map[i][j]=0;
58                  }
59               }
60               while(m--)
61               {
62                  getchar();
63                  scanf("%s",temp);
64                  int i=1,len=strlen(temp);
65                  s=e=w=0;
66                  while(temp[i]!=','){s=s*10+temp[i]-'0';i++;}
67                  i++;
68                  while(temp[i]!=')'){e=e*10+temp[i]-'0';i++;}
69                  i++;
70                  while(i<len){w=w*10+temp[i]-'0';i++;}
71                  map[s][e]+=w;
72               }
73               while(np--)
74               {
75                  scanf("%s",temp);
76                  int i=1,len=strlen(temp);
77                  s=w=0;
78                  while(temp[i]!=')'){s=s*10+temp[i]-'0';i++;}
79                  i++;
80                  while(i<len){w=w*10+temp[i]-'0';i++;}
81                  map[n][s]+=w;
82               }
83               while(nc--)
84               {
85                  scanf("%s",temp);
86                  int i=1,len=strlen(temp);
87                  s=w=0;
88                  while(temp[i]!=')'){s=s*10+temp[i]-'0';i++;}
89                  i++;
90                  while(i<len){w=w*10+temp[i]-'0';i++;}
91                  map[s][n+1]+=w;
92               }
93               answer=0;
94               printf("%d\n",bfs());
95        }
96        return 0;
97     }

虽然这个算法比较好理解,但是在时间上面确实是十分的底下的。。

所以开始了sap的学习,现在设置一个距离标号为dis[i],表示i节点和终点的距离。首先先全部初始化为0,然后若现在有一条路径k->t->终点,则表示dis[k]=dis[t]+1;ok了,说了这个,说实话应该会看的比较懂的。。

不过下面有两种样式的代码,一个是递归的,比较好理解,而非递归的就是在模拟递归一样,不要被代码长度吓到,不过说实话,我那个时候还是被吓到了的…

View Code
 1 #include<iostream>
 2 #define min(a,b) a<b?a:b
 3 #define Inf 0x7fffffff
 4 #define N 110
 5 using namespace std;
 6 int n,np,nc,m,map[N][N],dis[N],gap[N];
 7 int s,e,w;//起点、终点、权值 
 8 char temp[20];
 9 int dfs(int src,int aug)
10 {
11      if(src==n+1)return aug;
12      int flow=0,min_d=n+1;
13      for(int i=0;i<=n+1;i++)
14      {
15          if(map[src][i])
16          {
17              if(dis[src]==dis[i]+1)
18              {
19                  int t=dfs(i,min(aug-flow,map[src][i]));
20                  map[src][i]-=t;
21                  map[i][src]+=t;
22                  flow+=t;
23                  if(aug==flow)break;
24              }
25              min_d=min(min_d,dis[i]);
26          }
27      }
28      if(!flow)
29      {
30          if(!(gap[dis[src]]--))dis[n]=n+2;
31          ++gap[dis[src]=min_d+1];
32      }
33      return flow; 
34 }
35 int main()
36 {
37     while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
38     {
39          for(int i=0;i<=n+1;i++)
40              for(int j=0;j<=n+1;j++)
41                 map[i][j]=0;
42          while(m--)
43          {
44                 scanf("%s",temp);
45                 int i=1,len=strlen(temp);
46                 s=e=w=0;
47                 while(temp[i]!=','){s=s*10+temp[i]-'0';i++;}i++;
48                 while(temp[i]!=')'){e=e*10+temp[i]-'0';i++;}i++;
49                 while(i<len){w=w*10+temp[i]-'0';i++;}
50                 map[s][e]+=w;
51          }
52          while(np--)
53          {
54                 scanf("%s",temp);
55                 int i=1,len=strlen(temp);
56                 s=w=0;
57                 while(temp[i]!=')'){s=s*10+temp[i]-'0';i++;}i++;
58                 while(i<len){w=w*10+temp[i]-'0';i++;}
59                 map[n][s]+=w;
60          }
61          while(nc--)
62          {
63                 scanf("%s",temp);
64                 int i=1,len=strlen(temp);
65                 s=w=0;
66                 while(temp[i]!=')'){s=s*10+temp[i]-'0';i++;}i++;
67                 while(i<len){w=w*10+temp[i]-'0';i++;}
68                 map[s][n+1]=w;
69          }
70          int answer=0;
71          for(int i=0;i<=n+1;i++)dis[i]=gap[i]=0;
72          gap[0]=n+1;
73          while(dis[n]<=n+1)answer+=dfs(n,Inf);
74          printf("%d\n",answer);
75     }
76     return 0;   
77 }

 

View Code
  1 #include<iostream>
  2 #define min(a,b) a<b?a:b
  3 #define Inf 0x7fffffff
  4 #define N 110
  5 using namespace std;
  6 int n,np,nc,m,map[N][N],dis[N],gap[N],answer;
  7 int s,e,w;//起点、终点、权值 
  8 int back_flow[N],cur_arc[N],pre[N],neck[N];
  9 char temp[20];
 10 void bfs()
 11 {
 12     int cur_flow,flag,min_dis,temp,cur;
 13     cur=n;
 14     cur_flow=Inf;
 15     neck[n]=n;
 16     while(dis[n]<=n+1)
 17     {
 18          back_flow[cur]=cur_flow;
 19          flag=0;
 20          for(int i=cur_arc[cur];i<=n+1;i++)
 21          {
 22              if(map[cur][i]&&dis[cur]==dis[i]+1)
 23              {   
 24                  pre[i]=cur;
 25                  cur_arc[cur]=i;
 26                  flag=1;
 27                  if(map[cur][i]<cur_flow)
 28                  {
 29                      cur_flow=map[cur][i];
 30                      neck[i]=cur; 
 31                  }
 32                  else
 33                  {
 34                      neck[i]=neck[cur]; 
 35                  }          
 36                  cur=i;
 37                  if(cur==n+1)
 38                  {
 39                      answer+=cur_flow;
 40                      while(cur!=n)
 41                      {
 42                          map[pre[cur]][cur]-=cur_flow;
 43                          back_flow[cur]-=cur_flow;
 44                          map[cur][pre[cur]]+=cur_flow;
 45                          cur=pre[cur]; 
 46                      }            
 47                      cur=neck[cur];
 48                      cur_flow=back_flow[cur]; 
 49                  }
 50                  break;
 51              }
 52          }
 53          if(flag)continue;
 54          min_dis=n+1;
 55          for(int i=0;i<=n+1;i++)
 56          {
 57              if(map[cur][i]&&dis[i]<min_dis)
 58              {
 59                min_dis=dis[i];
 60                temp=i;
 61              }
 62          }
 63          cur_arc[cur]=temp;
 64          gap[dis[cur]]--;
 65          if(gap[dis[cur]]==0)break;
 66          dis[cur]=min_dis+1;
 67          gap[dis[cur]]++;
 68          if(cur!=n)
 69          {
 70             cur=pre[cur];
 71             cur_flow=back_flow[cur];
 72          }
 73     }
 74 }
 75 int main()
 76 {
 77     while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF)
 78     {
 79          for(int i=0;i<=n+1;i++)
 80              for(int j=0;j<=n+1;j++)
 81                 map[i][j]=0;
 82          while(m--)
 83          {
 84                 scanf("%s",temp);
 85                 int i=1,len=strlen(temp);
 86                 s=e=w=0;
 87                 while(temp[i]!=','){s=s*10+temp[i]-'0';i++;}i++;
 88                 while(temp[i]!=')'){e=e*10+temp[i]-'0';i++;}i++;
 89                 while(i<len){w=w*10+temp[i]-'0';i++;}
 90                 map[s][e]+=w;
 91          }
 92          while(np--)
 93          {
 94                 scanf("%s",temp);
 95                 int i=1,len=strlen(temp);
 96                 s=w=0;
 97                 while(temp[i]!=')'){s=s*10+temp[i]-'0';i++;}i++;
 98                 while(i<len){w=w*10+temp[i]-'0';i++;}
 99                 map[n][s]+=w;
100          }
101          while(nc--)
102          {
103                 scanf("%s",temp);
104                 int i=1,len=strlen(temp);
105                 s=w=0;
106                 while(temp[i]!=')'){s=s*10+temp[i]-'0';i++;}i++;
107                 while(i<len){w=w*10+temp[i]-'0';i++;}
108                 map[s][n+1]=w;
109          }
110          answer=0;
111          for(int i=0;i<=n+1;i++)cur_arc[i]=dis[i]=gap[i]=0;
112          gap[0]=n+2;
113          bfs();
114          printf("%d\n",answer);
115     }
116     return 0;   
117 }

 

posted @ 2012-09-04 15:51  诺小J  阅读(159)  评论(0编辑  收藏  举报