zoukankan      html  css  js  c++  java
  • 网络流24题总结和题解

    大体按照难度阵营

    t0 

    1.飞行员配对方案问题 

    这是个二分图匹配模板 但是这个输出方案套路还是要 掌握起来~

    大概是 我们跑网络流 一定能获得两个东西

    1.最大最小可行流数值和最大流数值

    2.一个可行的跑的方案 这个方案的特点是按照加边顺序进行增广 也就是说 加边满足字典序时 就可以按字典序跑了

    我们得到1 不停地增广 我们得到二 就是寻找跑满流量的正向边

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define maxn 10005
     5 #define inf 200000000
     6 int n,m,k=0,l,a,b,c,d[maxn],cur[maxn],visit[maxn],s=0,t;
     7 struct edge{int from,to,cap,flow;};vector<int>g[maxn];vector<edge>edges;
     8 void add_edge(int f,int t,int c){g[f].push_back(k);g[t].push_back(k+1);
     9     edges.push_back({f,t,c,0});edges.push_back({t,f,0,0});k+=2;
    10 }bool bfs(){queue<int>q;q.push(s);for(int i=1;i<=t;i++)d[i]=inf;d[s]=0;
    11     visit[s]=1,q.push(s);
    12     while(!q.empty()){int u=q.front();q.pop();visit[u]=0;
    13         for(int i=0;i<g[u].size();i++){edge &e=edges[g[u][i]];
    14             if(e.cap>e.flow&&d[e.to]>d[u]+1){d[e.to]=d[u]+1;if(!visit[e.to])q.push(e.to),visit[e.to]=1;
    15             }
    16         }
    17     }return d[t]!=inf;
    18 }ll dfs(int x,int a){if(x==t||a==0)return a;ll f=0,flow=0;
    19     for(int &i=cur[x];i<g[x].size();i++){edge &e=edges[g[x][i]];
    20         if(d[e.to]==d[x]+1&&(f=dfs(e.to,min(e.cap-e.flow,a)))){
    21             e.flow+=f,edges[g[x][i]^1].flow-=f,flow+=f,a-=f;
    22         }
    23     }return flow;
    24 }ll mf(ll s,ll t){ll flow=0;
    25     while(bfs()){memset(cur,0,sizeof(cur));
    26         flow+=dfs(s,inf);
    27     }return flow;
    28 }int main(){cin>>m>>n;cin>>a>>b;t=n+1;
    29     for(int i=1;i<=m;i++)add_edge(s,i,1);for(int i=m+1;i<=n;i++)add_edge(i,t,1);
    30     while(a!=-1)add_edge(a,b,1),cin>>a>>b;
    31     cout<<mf(s,t)<<endl;
    32     for(int i=1;i<=m;i++)for(int j=0;j<g[i].size();j++){
    33             edge &e=edges[g[i][j]];if(e.flow==1)cout<<i<<" "<<e.to<<endl;
    34     }return 0;
    35 }
    View Code

    2.负载平衡问题

    这不知道跟网络流有个π关系

    啊 毫无关系 结论套一下就行 结论还是要掌握起来的

    代码吧

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int N=105;
     5 
     6 ll n,a[N],sum,s[N];
     7 
     8 int main()
     9 {
    10     cin>>n;
    11     for(int i=1;i<=n;i++)
    12     
    13     cin>>a[i],
    14     
    15     sum+=a[i];
    16     
    17     sum/=n;
    18     
    19     for(int i=1;i<=n;i++)
    20     
    21     a[i]-=sum,
    22     
    23     s[i]=s[i-1]+a[i];
    24     
    25     sort(s+1,s+n+1);
    26     
    27     sum=0;
    28     
    29     for(int i=1;i<=n;i++)
    30     
    31     sum+=abs(s[n/2+1]-s[i]);
    32     
    33     cout<<sum;
    34     return 0;
    35 }
    View Code

    t1

    1.餐巾计划问题

    首先费用流

    这个题也不知道是不是我搞错了 bzoj好像数据范围不大对 是不是有网络流以外的做法 我也不得而知

    这个题是个这样的模型:点代表天 每个天有s种决策 就拆为s个点 构造分层图 图与图之间链接操作边(边代表操作)

    简单来说叫做

    第一类:决策拆点

    难度评价 思维难度 2 代码难度 2 总体较为中档

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define maxn 4005
     4 #define ll long long
     5 #define inf 214700000
     6 struct edge{int from,to,cap,flow,cost;};
     7 int k=0;vector<edge>edges;vector<int>g[maxn];
     8 void add_edge(int f,int t,int v,int cost){g[f].push_back(k),g[t].push_back(k+1),k+=2,edges.push_back({f,t,v,0,cost}),edges.push_back({t,f,0,0,-cost});}
     9 int n,m,visit[maxn],d[maxn],a[maxn],p[maxn],aa,b,c,dd,s,t,m1,t1,m2,t2,x;
    10 ll sum=0,flow=0;
    11 bool spfa(){for(int i=1;i<maxn;i++)d[i]=inf;a[s]=inf;
    12     memset(visit,0,sizeof(visit));
    13     queue<int>q;q.push(s),d[s]=0;visit[s]=1;
    14     while(!q.empty()){int u=q.front();q.pop();visit[u]=0;
    15         for(int i=0;i<g[u].size();i++){edge &e=edges[g[u][i]];
    16             if(d[e.to]>d[u]+e.cost&&e.cap>e.flow){p[e.to]=g[u][i],a[e.to]=min(a[u],e.cap-e.flow),d[e.to]=d[u]+e.cost;
    17                 if(!visit[e.to])q.push(e.to),visit[e.to]=1;
    18             }
    19         }        
    20     }if(d[t]==inf)return 0;
    21     flow+=1ll*a[t];
    22     sum+=1ll*d[t]*a[t];int u=t;
    23     while(u!=s){edges[p[u]].flow+=a[t];edges[p[u]^1].flow-=a[t];
    24         u=edges[p[u]].from;
    25     }return true; 
    26 }
    27 int main(){cin>>n;s=0,t=2*n+1;
    28     for(int i=1;i<=n;i++){scanf("%d",&x);
    29         add_edge(s,i,x,0);add_edge(i+n,t,x,0);
    30     }scanf("%d%d%d%d%d",&m,&t1,&m1,&t2,&m2);
    31     for(int i=1;i<=n;i++){
    32         if(i+1<=n)add_edge(i,i+1,inf,0);if(i+t1<=n)add_edge(i,i+n+t1,inf,m1);
    33         if(i+t2<=n)add_edge(i,i+n+t2,inf,m2);add_edge(s,i+n,inf,m);
    34     }while(spfa());cout<<sum<<endl;
    35 }
    View Code

     

  • 相关阅读:
    char*,const char*和string的相互转换[转]
    1.0到2.0 的变化
    Hello项目分析
    VS上编译Lua5.1.4生成静态库
    cocos2dx 自带动画
    asp.net2.0安全性(Login系列控件)
    用js实现的对css的一些操作方法
    mapxtreme开发小结3(c#)
    asp.net页面事件执行顺序
    access与SqlServer 之时间与日期及其它SQL语句比较
  • 原文地址:https://www.cnblogs.com/iboom/p/10045084.html
Copyright © 2011-2022 走看看