网络流

最大流:

详情搜索,

算法:Dinic ISAP 预流推进算法;

Dinic模板:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<queue>
  7 using namespace std;
  8 const int maxn = 10101;
  9 
 10 struct Edge
 11 {
 12     int from,to,cap,flow;
 13     Edge(int from,int to,int cap,int flow):from(from),to(to),cap(cap),flow(flow)
 14     {}    
 15 };
 16 
 17 struct Dinic{
 18     vector<Edge> edges;
 19     vector<int> G[maxn];
 20     int cur[maxn];
 21     int vis[maxn];
 22     int d[maxn];
 23     int s;int t;
 24     static const int INF = 1<<29;
 25     
 26     void AddEdge(int from,int to,int cap)
 27     {
 28         edges.push_back(Edge(from,to,cap,0));
 29         edges.push_back(Edge(to,from,0,0));
 30         int m = edges.size();
 31         G[from].push_back(m-2);
 32         G[to].push_back(m-1);
 33     }
 34     
 35     
 36     bool bfs()
 37     {
 38         memset(vis,0,sizeof(vis));
 39         queue<int> Q;
 40         Q.push(s);
 41         d[s] = 0;
 42         vis[s] = 1;
 43         while(!Q.empty())
 44         {
 45             int u = Q.front();Q.pop();
 46             for(int i = 0;i < G[u].size();i++)
 47             {
 48                 Edge& e = edges[G[u][i]];
 49                 if(!vis[e.to]&&e.cap > e.flow )
 50                 {
 51                     d[e.to] = d[u] +1;
 52                     vis[e.to] = 1;
 53                     Q.push(e.to);
 54                 }
 55             }
 56         }        
 57         return vis[t];
 58     }
 59 
 60     int dfs(int now,int a)
 61     {
 62         if(now == t||a == 0) return a;
 63         int flow  = 0,f;
 64         for(int& i = cur[now];i < G[now].size();i++)
 65         {
 66             Edge& e = edges[G[now][i]];
 67             if(d[e.to] == d[now] + 1&&(f = (dfs(e.to,min(a,e.cap-e.flow)))) > 0)
 68             {
 69                 flow += f;
 70                 e.flow  += f;
 71                 edges[G[now][i]^1].flow -= f;
 72                 a -= f;
 73                 
 74                 if(a == 0) break;
 75             }
 76         }
 77         return flow;        
 78     }
 79     
 80     int MaxFlow(int s,int t)
 81     {
 82         this->s = s;this -> t = t; 
 83         int flow = 0;
 84         while(bfs())
 85         {
 86             memset(cur,0,sizeof(cur));
 87             flow += dfs(s,INF);
 88         }
 89         return flow;
 90     }
 91 }solver;
 92 
 93 
 94 int main()
 95 {
 96     int n,m;
 97     scanf("%d%d",&n,&m);
 98     for(int i = 0;i < n;i++)
 99     {
100         int from,to,cap;
101         scanf("%d%d%d",&from,&to,&cap);
102         solver.AddEdge(from,to,cap);
103     }    
104     cout<<solver.MaxFlow(1,m)<<endl;
105     
106     
107     return 0;
108 }
Dinic

Dinic优点,容易理解+思路明晰。不断用BFS构造分层图,再用DFS找阻塞流增广。正常O(n2m)容量都为1的话。渐进时间为Ο(min(n2/3,m1/2)m),二分图则是O(n1/2m);

附带一个板子题 codevs 1993

二分图最大匹配:飞行员配对方案问题

简单的设置下超级源和超级汇就好;傻逼错误:每次加边都加连源点和起点,重点和汇点,导致超多的重边,导致百分百全部匹配上,格外连一下就搞定,我这还调试了30分钟,实乃傻逼也。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<vector>
  5 #include<algorithm>
  6 #include<stack>
  7 #include<queue>
  8 #include<cstdlib>
  9 
 10 using namespace std;
 11 const int maxn = 5010;
 12 const int INF = 1<<29;
 13 
 14 struct Edge{
 15     int from,to,cap,flow;
 16     Edge(int from,int to,int cap,int flow):
 17         from(from),to(to),cap(cap),flow(flow){}
 18 };
 19 
 20 struct Dinic
 21 {
 22     int s,t;
 23     vector<Edge> edges;
 24     vector<int> G[maxn];
 25     int Link[maxn];
 26     int d[maxn];
 27     int vis[maxn];
 28     int cur[maxn];
 29     
 30     int AddEdge(int from,int to,int cap)
 31     {
 32         edges.push_back(Edge(from,to,cap,0));
 33         edges.push_back(Edge(to,from,0,0));
 34         int m = edges.size();
 35         G[from].push_back(m-2);
 36         G[to].push_back(m-1);
 37     }
 38     
 39     bool bfs()
 40     {
 41         memset(vis,0,sizeof(vis));
 42         queue<int> Q;
 43         memset(d,0,sizeof(d));
 44         d[s] = 0;
 45         vis[s] = 1;
 46         Q.push(s);
 47         while(!Q.empty())
 48         {
 49             int u = Q.front();Q.pop();
 50             for(int i = 0;i < G[u].size();i++)
 51             {
 52                 Edge& e = edges[G[u][i]];
 53                 if(!vis[e.to] && e.cap > e.flow)
 54                 {
 55                     vis[e.to] = 1;
 56                     d[e.to] = d[u] +1;
 57                     Q.push(e.to);
 58                 }    
 59             }        
 60         }
 61         return vis[t];
 62     }
 63     
 64     int dfs(int now,int a)
 65     {
 66         if(now == t|| a== 0) return a;
 67         int flow = 0,f;
 68         for(int& i = cur[now];i < G[now].size();i++)
 69         {
 70             Edge& e = edges[G[now][i]];
 71             if(d[e.to] == d[now] + 1&& (f = dfs(e.to,min(a,e.cap - e.flow))) > 0 )
 72             {
 73                 Link[e.from] = e.to;
 74                 flow += f;
 75                 a -= f;
 76                 e.flow += f;
 77                 edges[G[now][i]^1].flow -= f;
 78                 if(a == 0) break;
 79             }
 80         }
 81         return flow;
 82     }
 83     
 84     int MaxFlow(int s,int t)
 85     {
 86         this-> s = s;this -> t = t;
 87         int flow = 0;
 88         while(bfs())
 89         {
 90             memset(cur,0,sizeof(cur));
 91             flow += dfs(s,1);
 92         }
 93         return flow;
 94     }
 95     
 96     void print(int n)
 97     {
 98         for(int i = 1;i <= n;i++)
 99             if(Link[i])
100                 printf("%d %d\n",i,Link[i]);
101     }
102 }solver;
103 
104 
105 int main()
106 {
107     int n,m;
108     scanf("%d%d",&n,&m);
109     for(int i = 1;i <= n;i++) solver.AddEdge(0,i,1);
110     for(int i = n+1;i<= m;i++) solver.AddEdge(i,m+1,1);
111     int from,to;
112     while(scanf("%d%d",&from,&to) == 2&&from != -1&&to != -1)
113     {
114         solver.AddEdge(from,to,1);            
115     }
116     int flow = solver.MaxFlow(0,m+1);        
117     cout<<flow<<endl;
118     solver.print(n);
119     return 0;
120 }
二分图最大基数匹配

 

posted @ 2017-03-13 13:42  rsqppp  阅读(162)  评论(0)    收藏  举报