ZOJ 2364 Data Transmission (最大流:Dinic+贪心预流)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2364

裸的最大流。。。

用了Dinic、ISAP、HLPP都TLE。。。

然后在网上看到了个贪心预流的优化,就AC了,2030ms

贪心预流仅用于预处理分层图网络流

HLPP一般适合处理分层图,但是怎么加了贪心预流还是T了。。DINIC和ISAP加了贪心预流就AC了。。

同时附上Dinic和贪心预流模板~

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<string>
  6 #include<cmath>
  7 #include<set>
  8 #include<list>
  9 #include<map>
 10 #include<iterator>
 11 #include<cstdlib>
 12 #include<vector>
 13 #include<queue>
 14 #include<stack>
 15 #include<algorithm>
 16 #include<functional>
 17 using namespace std;
 18 typedef long long LL;
 19 #define ROUND(x) round(x)
 20 #define FLOOR(x) floor(x)
 21 #define CEIL(x) ceil(x)
 22 //const int maxn=0;
 23 //const int inf=0x3f3f3f3f;
 24 const LL inf64=0x3f3f3f3f3f3f3f3fLL;
 25 const double INF=1e30;
 26 const double eps=1e-6;
 27 /**
 28 *最大流最小割:加各种优化的Dinic算法($O(V^2E)$)
 29 *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇)
 30 *输出:Dinic(NdFlow)(最大流),MinCut()(最小割)(需先求最大流)
 31 *打印路径方法:按反向边(i&1)的flow 找,或者按边的flow找
 32 */
 33 const int maxn=1510;
 34 const int maxm=600010;
 35 const int inf=0x3f3f3f3f;
 36 struct Edge
 37 {
 38     int u,v;
 39     int cap,flow;
 40     int next;
 41 } edge[maxm];
 42 int head[maxn],edgeNum;//需初始化
 43 int n,m,d[maxn],cur[maxn];
 44 int st,ed;
 45 bool vis[maxn];
 46 void addSubEdge(int u,int v,int cap,int flow)
 47 {
 48     edge[edgeNum].u=u;
 49     edge[edgeNum].v=v;
 50     edge[edgeNum].cap=cap;
 51     edge[edgeNum].flow=flow;
 52     edge[edgeNum].next=head[u];
 53     head[u]=edgeNum++;
 54     cur[u]=head[u];
 55 }
 56 void addEdge(int u,int v,int cap)
 57 {
 58     addSubEdge(u,v,cap,0);
 59     addSubEdge(v,u,0,0);//注意加反向0 边
 60 }
 61 bool BFS()
 62 {
 63     queue<int> Q;
 64     memset(vis, 0, sizeof(vis));
 65     Q.push(st);
 66     d[st]=0;
 67     vis[st]=1;
 68     while (!Q.empty())
 69     {
 70         int u=Q.front();
 71         Q.pop();
 72         for(int i=head[u]; i!=-1; i=edge[i].next)
 73         {
 74             int v=edge[i].v;
 75             int w=edge[i].cap-edge[i].flow;
 76             if(w>0 && !vis[v])
 77             {
 78                 vis[v]=1;
 79                 Q.push(v);
 80                 d[v]=d[u]+1;
 81                 if(v==ed) return 1;
 82             }
 83         }
 84     }
 85     return false;
 86 }
 87 int Aug(int u, int a)
 88 {
 89     if (u==ed) return a;
 90     int aug=0, delta;
 91     for(int &i=cur[u]; i!=-1; i=edge[i].next)
 92     {
 93         int v=edge[i].v;
 94         int w=edge[i].cap-edge[i].flow;
 95         if (w>0 && d[v]==d[u]+1)
 96         {
 97             delta = Aug(v, min(a,w));
 98             if (delta)
 99             {
100                 edge[i].flow += delta;
101                 edge[i^1].flow -= delta;
102                 aug += delta;
103                 if (!(a-=delta)) break;
104             }
105         }
106     }
107     if (!aug) d[u]=-1;
108     return aug;
109 }
110 int Dinic(int NdFlow)
111 {
112     int flow=0;
113     while (BFS())
114     {
115         memcpy(cur,head,sizeof(int)*(n+1));
116         flow += Aug(st,inf);
117         /*如果超过指定流量就return 掉*/
118         if(NdFlow==inf) continue;
119         if(flow > NdFlow) break;
120     }
121     return flow;
122 }
123 /*残余网络*/
124 void Reduce()
125 {
126     for(int i=0; i<edgeNum; i++) edge[i].cap-=edge[i].flow;
127 }
128 /*清空流量*/
129 void ClearFlow()
130 {
131     for(int i=0; i<edgeNum; i++) edge[i].flow=0;
132 }
133 /*求最小割*/
134 vector<int> MinCut()
135 {
136     BFS();
137     vector<int> ans;
138     for(int u=0; u<n; u++)
139     {
140         if(!vis[u]) continue;
141         for(int i=head[u]; i!=-1; i=edge[i].next)
142         {
143             if(i&1) continue;/*忽略反向边*/
144             int v=edge[i].v;
145             int w=edge[i].cap;
146             if(!vis[v]&&w>0) ans.push_back(i);
147         }
148     }
149     return ans;
150 }
151 
152 /**
153 *贪心预流:用于分层图Dinic预处理(从0到n-1)
154 *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇),rk[i]=i,level[](分层图的层次)
155 *输出:GreedyPreFlow()(预处理Dinic)
156 */
157 int in[maxn],out[maxn];
158 int level[maxn],rk[maxn];
159 bool cmp(const int &i,const int &j)
160 {
161     return level[i]<level[j];
162 }
163 void GreedyPreFlow()
164 {
165     memset(in, 0, sizeof (in));
166     memset(out, 0, sizeof (out));
167     sort(rk, rk+n, cmp);
168     in[st] = inf;
169     for (int i = 0; i < n; ++i)
170     {
171         int u = rk[i];
172         for (int j = head[u]; j!=-1; j = edge[j].next)
173         {
174             int v = edge[j].v, w = edge[j].cap-edge[j].flow;
175             if (!(j & 1) && in[u] > out[u])
176             {
177                 int f = min(w, in[u]-out[u]);
178                 in[v] += f, out[u] += f;
179             }
180         }
181     }
182     memset(in, 0, sizeof (in));
183     in[ed] = inf;
184     for (int i = n-1; i >= 0; --i)
185     {
186         int v = rk[i];
187         for (int j = head[v]; j!=-1; j = edge[j].next)
188         {
189             int u = edge[j].v, w = edge[j^1].cap-edge[j^1].flow;
190             if (j & 1 && out[u] > in[u])
191             {
192                 int f = min(w, min(out[u]-in[u], in[v]));
193                 in[u] += f, in[v] -= f;
194                 edge[j].flow -= f, edge[j^1].flow += f;
195             }
196         }
197     }
198 }
199 
200 int N,M,L;
201 void init()
202 {
203     memset(head,-1,sizeof(head));
204     edgeNum=0;
205 }
206 void input()
207 {
208     scanf("%d%d%d",&N,&M,&L);
209     int x=0;
210     int idx=0;
211     st=0,ed=0;
212     for(int i=0; i<N; i++)
213     {
214         scanf("%d",&x);
215         rk[i]=i;
216         level[i]=x;
217         if(x==1) st=i;
218         if(x==L) ed=i;
219     }
220     for(int i=0; i<M; i++)
221     {
222         int u,v,w;
223         scanf("%d%d%d",&u,&v,&w);
224         u--,v--;
225         addEdge(u,v,w);
226     }
227     n=N;
228 }
229 void solve()
230 {
231     GreedyPreFlow();
232     ISAP(inf);
233 //    cout<<HLPP()<<endl;
234 //    cout<<Dinic(inf)<<endl;
235     for(int i=0; i<edgeNum; i+=2) printf("%d\n",edge[i].flow);
236 }
237 void output()
238 {
239     //
240 }
241 int main()
242 {
243 //    std::ios_base::sync_with_stdio(false);
244 //    freopen("in.cpp","r",stdin);
245     int T;
246     scanf("%d",&T);
247     while(T--)
248     {
249         init();
250         input();
251         solve();
252         output();
253     }
254     return 0;
255 }
View Code

 

posted @ 2013-09-25 13:50  xysmlx  阅读(284)  评论(0编辑  收藏  举报