POJ 3469Dual Core CPU(最小割)

本文对比了两种最大流算法:SAP和Dinic在POJ3469问题上的性能表现。通过具体实现和测试,发现对于大规模数据集(n<=20000),SAP算法在非递归效率上优于Dinic算法的递归写法,但Dinic的非递归版本也展现出了良好的性能。

【题意】

【分析】

【建图】

 

留着有空再写

 

【Mark】

数据较大,n<=20000。使用dinic的递归写法跑了7s+,非递归TLE.sap跑了2s+。

谁说非递归效率高?

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 const int N=20100;
  9 const int M=200200;
 10 const int inf=100000000;
 11 
 12 struct node
 13 {
 14     int v,f;
 15     int next;
 16 } edge[8*M];
 17 int head[N],num;
 18 int n,m;
 19 int s,t,NN;
 20 
 21 void init()
 22 {
 23     memset(head,-1,sizeof(head));
 24     num=0;
 25 }
 26 
 27 void addege(int u,int v,int f)
 28 {
 29     edge[num].v=v;
 30     edge[num].f=f;
 31     edge[num].next=head[u];
 32     head[u]=num++;
 33     edge[num].v=u;
 34     edge[num].f=0;
 35     edge[num].next=head[v];
 36     head[v]=num++;
 37 }
 38 
 39 int sap()
 40 {
 41     int pre[N],cur[N],dis[N],gap[N];
 42     int flow=0,aug=inf,u;
 43     bool flag;
 44     int i;
 45     for(i=1; i<=NN; i++)
 46     {
 47         cur[i]=head[i];
 48         gap[i]=dis[i]=0;
 49     }
 50     gap[s]=NN;
 51     u=pre[s]=s;
 52     while(dis[s]<NN)
 53     {
 54         flag=0;
 55         for(int &j=cur[u]; j!=-1; j=edge[j].next)
 56         {
 57             int v=edge[j].v;
 58             if(edge[j].f>0 && dis[u]==dis[v]+1)
 59             {
 60                 flag=1;
 61                 if(edge[j].f<aug) aug=edge[j].f;
 62                 pre[v]=u;
 63                 u=v;
 64                 if(u==t)
 65                 {
 66                     flow+=aug;
 67                     while(u!=s)
 68                     {
 69                         u=pre[u];
 70                         edge[cur[u]].f-=aug;
 71                         edge[cur[u]^1].f+=aug;
 72                     }
 73                     aug=inf;
 74                 }
 75                 break;
 76             }
 77         }
 78         if(flag) continue;
 79         int mindis=NN;
 80         for(int j=head[u]; j!=-1; j=edge[j].next)
 81         {
 82             int v=edge[j].v;
 83             if(edge[j].f>0 && dis[v]<mindis)
 84             {
 85                 mindis=dis[v];
 86                 cur[u]=j;
 87             }
 88         }
 89         if((--gap[dis[u]])==0) break;
 90         gap[dis[u]=mindis+1]++;
 91         u=pre[u];
 92     }
 93     return flow;
 94 }
 95 
 96 int main()
 97 {
 98     while (scanf("%d%d",&n,&m)==2)
 99     {
100         int i,j;
101         int a,b,w;
102         s=0;
103         t=n+1;
104         NN=n+2;
105         init();
106         for(i=1; i<=n; i++)
107         {
108             scanf("%d%d",&a,&b);
109             addege(s,i,a);
110             addege(i,t,b);
111         }
112         for(i=1; i<=m; i++)
113         {
114             scanf("%d%d%d",&a,&b,&w);
115             addege(a,b,w);
116             addege(b,a,w);
117         }
118         printf("%d\n",sap());
119     }
120     return 0;
121 }
poj3469(sap)
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 #define INF 1e8
  9 #define MAX_VECT 20005
 10 #define MAX_EDGE 2200000
 11 
 12 /************************************************************************/
 13 /*    Name: dinic
 14 /*  Description: Find the max flow of the network from start to
 15                  end point
 16 /*  Variable Description: to[] - end point of the current edge
 17                           next[] - the next edge which also comes from
 18                                    the same point as current edge
 19                           cap[] - the capability of the current edge
 20                           v[] - the first edge index which comes from the
 21                                 the current point
 22                           d[] - the layer number of current point
 23 /************************************************************************/
 24 
 25 
 26 int to[MAX_EDGE], next[MAX_EDGE], cap[MAX_EDGE], tot;
 27 int v[MAX_VECT], d[MAX_VECT], queue[MAX_VECT], n;
 28 int S, T;
 29 inline void single_insert(int _u, int _v, int var)
 30 {
 31     to[tot] = _v;
 32     cap[tot] = var;
 33     next[tot] = v[_u];
 34     v[_u] = tot++;
 35 }
 36 
 37 void insert(int from, int to,  int cap)
 38 {
 39     single_insert(from, to, cap);
 40     single_insert(to, from, 0);
 41 }
 42 
 43 bool bfs_initial()
 44 {
 45     memset(d, -1, sizeof(d));
 46     int bg, ed, x, y;
 47     bg = ed = d[S] = 0;
 48     queue[ed++] = S;
 49     while (bg < ed)
 50     {
 51         x = queue[bg++];
 52         for (int i = v[x]; i+1; i = next[i])
 53         {
 54             y = to[i];
 55             if (cap[i] && d[y] == -1)
 56             {
 57                 d[y] = d[x] + 1;
 58                 if (y == T) return true;
 59                 queue[ed++] = y;
 60             }
 61         }
 62     }
 63     return false;
 64 }
 65 
 66 int Find(int x, int low = INF)
 67 {
 68     if (x == T) return low;
 69     int ret, y, ans = 0;
 70     for (int i = v[x]; (i+1) && low; i = next[i])
 71     {
 72         y = to[i];
 73         if (cap[i] && d[y] == d[x] + 1 && (ret = Find(y, min(low, cap[i]))))
 74         {
 75             cap[i] -= ret;
 76             cap[i^1] += ret;
 77             low -= ret;
 78             ans += ret;
 79         }
 80     }
 81     return ans;
 82 }
 83 int dinic()
 84 {
 85     int ans = 0;
 86     while (bfs_initial())
 87         ans += Find(S);
 88     return ans;
 89 }
 90 
 91 
 92 int dinicc()
 93 {
 94     int ans = 0;
 95     while(bfs_initial())
 96     {
 97         int edge, x, y, back, iter = 1;
 98         while(iter)
 99         {
100             x = (iter == 1) ? S : to[queue[iter - 1]];
101             if (x == T)
102             {
103                 int minE, minCap = INF;
104                 for (int i = 1; i < iter; i++)
105                 {
106                     edge = queue[i];
107                     if (cap[edge] < minCap)
108                     {
109                         minCap = cap[edge];
110                         back = i;
111                     }
112                 }
113                 for (int i = 1; i < iter; i++)
114                 {
115                     edge = queue[i];
116                     cap[edge] -= minCap;
117                     cap[edge ^ 1] += minCap;
118                 }
119                 ans += minCap;
120                 iter = back;
121             }
122             else
123             {
124                 for (edge = v[x]; edge + 1; edge = next[edge])
125                 {
126                     y = to[edge];
127                     if (cap[edge] && d[y] == d[x] + 1)
128                         break;
129                 }
130                 if (edge+1)
131                     queue[iter++] = edge;
132                 else
133                 {
134                     d[x] = -1;
135                     iter--;
136                 }
137             }
138         }
139     }
140     return ans;
141 }
142 
143 int m;
144 
145 int main()
146 {
147     while (scanf("%d%d",&n,&m)==2)
148     {
149         memset(v,-1,sizeof(v));
150         tot = 0;
151         S = 0;
152         T = n+1;
153         for (int i=1;i<=n;i++)
154         {
155             int a,b;
156             scanf("%d%d",&a,&b);
157             insert(S,i,a);
158             insert(i,T,b);
159         }
160         for (int i=1;i<=m;i++)
161         {
162             int u,v,w;
163             scanf("%d%d%d",&u,&v,&w);
164             insert(u,v,w);
165             insert(v,u,w);
166         }
167         n++;
168         int ans = dinic();
169         printf("%d\n",ans);
170     }
171     return 0;
172 }
poj3469(dinic)

 

转载于:https://www.cnblogs.com/wangsouc/articles/3296908.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值