zoukankan      html  css  js  c++  java
  • 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
    ",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
  • 相关阅读:
    [译]Vulkan教程(03)开发环境
    [译]Vulkan教程(02)概况
    [译]Vulkan教程(01)入门
    CSharpGL(57)[译]Vulkan清空屏幕
    CSharpGL(56)[译]Vulkan入门
    CSharpGL(55)我是这样理解PBR的
    CSharpGL(54)用基于图像的光照(IBL)来计算PBR的Specular部分
    [译]背景:着色的物理和数学(4)
    [译]背景:着色的物理和数学(3)
    [译]背景:着色的物理和数学(2)
  • 原文地址:https://www.cnblogs.com/xysmlx/p/3338605.html
Copyright © 2011-2022 走看看