zoukankan      html  css  js  c++  java
  • 网络流24题——魔术球问题(有向无环图最小路径覆盖)

    链接:https://www.oj.swust.edu.cn/oj/problem/show/1739

    分析:

           有向无环图最小路径覆盖:给定有向无环图,求一个路径划分,使得每个点在且只在一条路径上,路径数要求最少。 对于这种问题,先把每个点看做一条路径,然后连边,每个点最多连出去一条,也最多被连一次,每有一个点被连,路径数-1,所有新增源汇点,连向所有的点,容量为1,然后拆点,保证每个点只过一次,求一下最大流flow,答案为n-flow。

           先考虑对于m个球,至少需要几个柱子。若a+b为平方数且a<b,从a向b连一条边,然后求一下整个图的最小路径覆盖,枚举球数,直到最小路径覆盖大于n。有两个地方需要优化一下:一个是每次求最大流后保留,加球后接着上次的增广;一个是对于n比较大的情况,可以设定一个值k,当m大于k时才求最大流,否则直接下一次加球。

      1 #include<iostream>
      2 #include<vector>
      3 #include<queue>
      4 #include<stack>
      5 #include<cstdio>
      6 #include<cstring>
      7 #include<algorithm>
      8 using namespace std;
      9 const int maxn=5e3+5,INF=1e9;
     10 const int maxball=1600;
     11 int idx=0,n;
     12 bool have[maxball+5];
     13 struct Pair{
     14     int x,y;
     15     Pair(int x,int y){
     16         this->x=x;this->y=y;
     17     }
     18 };
     19 bool Cmp(Pair a,Pair b){return a.y<b.y;}
     20 vector<Pair> p;
     21 struct Edge{
     22     int from,to,cap,flow;
     23     Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
     24 };
     25 struct ISAP{
     26     int n,s,t,flow;
     27     vector<Edge> edges;
     28     vector<int> G[maxn];
     29     bool vis[maxn];
     30     int d[maxn];
     31     int cur[maxn];
     32     int p[maxn];
     33     int num[maxn];
     34 
     35     void init(int n){
     36         this->n=n;
     37         flow=0;
     38         edges.clear();
     39         for(int i=0;i<n;i++)G[i].clear();
     40     }
     41 
     42     void AddEdge(int from,int to,int cap){
     43         edges.push_back(Edge(from,to,cap,0));
     44         edges.push_back(Edge(to,from,0,0));
     45         G[from].push_back(edges.size()-2);
     46         G[to].push_back(edges.size()-1);
     47     }
     48 
     49     void BFS(){
     50         memset(vis,0,sizeof(vis));
     51         queue<int> Q;
     52         Q.push(t);
     53         d[t]=0;
     54         vis[t]=1;
     55         while(!Q.empty()){
     56             int x=Q.front();Q.pop();
     57             for(int i=0;i<G[x].size();i++){
     58                 Edge &e=edges[G[x][i]^1];
     59                 if(e.flow==e.cap)continue;
     60                 if(!vis[e.from]){
     61                     vis[e.from]=1;
     62                     d[e.from]=d[x]+1;
     63                     Q.push(e.from);
     64                 }
     65             }
     66         }
     67     }
     68 
     69     int Augment(){
     70         int x=t,a=INF;
     71         while(x!=s){
     72             Edge &e=edges[p[x]];
     73             a=min(a,e.cap-e.flow);
     74             x=edges[p[x]].from;
     75         }
     76         x=t;
     77         while(x!=s){
     78             edges[p[x]].flow+=a;
     79             edges[p[x]^1].flow-=a;
     80             x=edges[p[x]].from;
     81         }
     82         return a;
     83     }
     84 
     85     int Maxflow(int s,int t){
     86         this->s=s;this->t=t;
     87         BFS();
     88         memset(num,0,sizeof(num));
     89         for(int i=0;i<n;i++)num[d[i]]++;
     90         int x=s;
     91         memset(cur,0,sizeof(cur));
     92         while(d[s]<n){
     93             if(x==t){
     94                 flow+=Augment();
     95                 x=s;
     96             }
     97             int ok=0;
     98             for(int i=cur[x];i<G[x].size();i++){
     99                 Edge &e=edges[G[x][i]];
    100                 if(e.cap>e.flow&&d[x]==d[e.to]+1){
    101                     ok=1;
    102                     p[e.to]=G[x][i];
    103                     cur[x]=i;
    104                     x=e.to;
    105                     break;
    106                 }
    107             }
    108             if(!ok){
    109                 int m=n-1;
    110                 for(int i=0;i<G[x].size();i++){
    111                     Edge &e=edges[G[x][i]];
    112                     if(e.cap>e.flow)m=min(m,d[e.to]);
    113                 }
    114                 if(--num[d[x]]==0)break;
    115                 num[d[x]=m+1]++;
    116                 cur[x]=0;
    117                 if(x!=s)x=edges[p[x]].from;
    118             }
    119         }
    120         return flow;
    121     }
    122     void Print(int c){
    123         int x=1,num=0;
    124         memset(have,0,sizeof(have));
    125         for(int i=1;i<=maxball&&num<c;i++){
    126             if(!have[i]){
    127                 printf("%d",i);
    128                 x=i;
    129                 num++;
    130                 while(!have[x]){
    131                     have[x]=true;
    132                     for(int j=0;j<G[x].size();j++){
    133                         Edge &e=edges[G[x][j]];
    134                         if(e.flow==0||e.to==0)continue;
    135                         x=e.to-maxball;
    136                         printf(" %d",x);
    137                     }
    138                 }
    139                 printf("
    ");
    140             }
    141         }
    142     }
    143 }isap;
    144 int main(){
    145 //    freopen("e:\in.txt","r",stdin);
    146     isap.init(2*maxball+2);
    147     for(int k=1;k<=100;k++){
    148         for(int i=1;k*k-i>i;i++){
    149             p.push_back(Pair(i,k*k-i));
    150         }
    151     }
    152     sort(p.begin(),p.end(),Cmp);
    153     scanf("%d",&n);
    154     int mi=n;
    155     if(n>=50)mi=1290;
    156     for(int m=1;;m++){
    157         isap.AddEdge(0,m,1);
    158         isap.AddEdge(m+maxball,2*maxball+1,1);
    159         while(idx<p.size()&&p[idx].y<=m){
    160             Pair &po=p[idx];
    161             isap.AddEdge(p[idx].x,p[idx].y+maxball,1);
    162             idx++;
    163         }
    164         if(m>=mi&&m-isap.Maxflow(0,2*maxball+1)==n+1){
    165             printf("%d
    ",m-1);
    166             isap.Print(n);break;
    167         }
    168     }
    169     return 0;
    170 }
  • 相关阅读:
    ajax_基础1
    省市数据库脚本TblArea.
    c#中怎么使用dos命
    Lambda表达式
    面试收录
    .Net牛逼程序猿要懂得
    Web.config 配置文件
    sql 查询所有数据库、表名、表字段总结
    Json在net与页面之间的传递
    『转』SAP统驭科目解释
  • 原文地址:https://www.cnblogs.com/7391-KID/p/7448118.html
Copyright © 2011-2022 走看看