• 网络流24T


    说出来你们可能不信,我咕了三个多星期了,今晚忽然不想再写题了,(写自闭了,把这边整理一下

    1. 洛谷P2756 飞行员配对问题  

    二分图匹配:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int m,n,a,b;
     4 const int MAXN = 105;
     5 int g[MAXN][MAXN];
     6 int linker[MAXN],used[MAXN];
     7 bool dfs(int u){
     8     for(int v=1;v<=n;v++){
     9         if(g[u][v]&&!used[v]){
    10             used[v]=true;
    11             if(linker[v]==-1||dfs(linker[v])){
    12                 linker[v]=u;//这俩匹配上了
    13                 return true;
    14             }
    15         }
    16     }
    17     return false;
    18 }
    19 int hungary(){
    20     int res = 0;
    21     memset(linker,-1, sizeof(linker));
    22     for(int u=1;u<=m;u++){
    23         memset(used,0, sizeof(used));
    24         if(dfs(u))
    25             res++;
    26     }
    27     return res;
    28 }
    29 int main(){
    30     ios::sync_with_stdio(false);
    31     cin>>m>>n;
    32     while (cin>>a>>b&&a!=-1&&b!=-1){
    33         g[a][b]=1;
    34     }
    35     cout<<hungary()<<endl;
    36     for(int i=1;i<=n;i++){
    37         if(linker[i]!=-1)
    38             cout<<linker[i]<<' '<<i<<endl;
    39     }
    40 }
    View Code

    最大流EK:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int INF = 0x3f3f3f3f;
     4 struct edge{
     5     int to,cap,rev;
     6 };
     7 vector<edge> g[250];
     8 bool used[250];
     9 void addEdge(int from,int to,int cap){//s到t流量为cap
    10     g[from].push_back((edge){to,cap,g[to].size()});
    11     g[to].push_back((edge){from,0,g[from].size()-1});
    12 }
    13 int dfs(int v,int t,int f){
    14     if(v==t)
    15         return f;
    16     used[v]=true;
    17     for(int i=0;i<g[v].size();i++){
    18         edge &e = g[v][i];
    19         if(!used[e.to]&&e.cap>0){//这算法竟该死的朴实
    20             int d = dfs(e.to,t,min(f,e.cap));
    21             if(d>0){
    22                 e.cap-=d;
    23                 g[e.to][e.rev].cap+=d;
    24                 return d;
    25             }
    26         }
    27     }
    28     return 0;
    29 }
    30 int max_flow(int s,int t){
    31     int flow = 0;
    32     for(;;){
    33         memset(used,0, sizeof(used));
    34         int f = dfs(s,t,INF);
    35         if(f==0) return flow;
    36         flow += f;
    37     }
    38 }
    39 int m,n,a,b;
    40 int main(){
    41     ios::sync_with_stdio(false);
    42     cin>>m>>n;
    43     while (cin>>a>>b&&a!=-1&&b!=-1){
    44         addEdge(a,b+m,1);
    45     }
    46     int S = 0,END = m+n+1;
    47     for(int i=1;i<=m;i++){
    48         addEdge(S,i,1);
    49     }
    50     for(int i=m+1;i<=m+n;i++){
    51         addEdge(i,END,1);
    52     }
    53     cout<<max_flow(0,n+m+1)<<endl;
    54     for(int i=1;i<=m;i++){
    55         for(int j=0;j<g[i].size();j++) {
    56             edge tmp = g[i][j];
    57             if (tmp.cap == 0&&g[i][j].to!=0) {
    58                 cout << i<<' '<<g[i][j].to-m<<endl;
    59                 break;
    60             }
    61         }
    62     }
    63 }
    View Code

    2.P4016 负载平衡问题

    费用流,首先相邻的仓库连流量INF费用为1的边。然后我们算出来平均数ave,如果这个仓库货物大于ave,就从源点连一个a[i]-ave的边,小于的话向汇点连一个ave-a[i]的边。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int MAXN = 10000;
      4 const int MAXM = 100000;
      5 const int INF = 0x3f3f3f3f;
      6 struct Edge{
      7     int to,next,cap,flow,cost;
      8 }edge[MAXM];
      9 int head[MAXN],tol;
     10 int pre[MAXN],dis[MAXN];
     11 bool vis[MAXN];
     12 int N;
     13 void init(int all){
     14     N = all;
     15     tol = 0;
     16     memset(head,-1, sizeof(head));
     17 }
     18 void addEdge(int u,int v,int cap,int cost){
     19     edge[tol].to=v;
     20     edge[tol].cap = cap;
     21     edge[tol].cost = cost;
     22     edge[tol].flow =0 ;
     23     edge[tol].next = head[u];
     24     head[u]=tol++;
     25     edge[tol].to=u;
     26     edge[tol].cap = 0;
     27     edge[tol].cost= -cost;
     28     edge[tol].flow=0;
     29     edge[tol].next=head[v];
     30     head[v]=tol++;
     31 }
     32 bool spfa(int s,int t){
     33     queue<int> q;
     34     for(int i=0;i<N;i++){
     35         dis[i]=INF;
     36         vis[i] = false;
     37         pre[i]=-1;
     38     }
     39     dis[s]=0;
     40     vis[s]=true;
     41     q.push(s);
     42     while (!q.empty()){
     43         int u = q.front();
     44         q.pop();
     45         vis[u]=false;
     46         for(int i=head[u];i!=-1;i=edge[i].next){
     47             int v = edge[i].to;
     48             if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
     49                 dis[v]=dis[u]+edge[i].cost;
     50                 pre[v]=i;
     51                 if(!vis[v]){
     52                     vis[v]=true;
     53                     q.push(v);
     54                 }
     55             }
     56         }
     57     }
     58     if(pre[t]==-1)return false;
     59     return true;
     60 }
     61 int minCostMaxFlow(int s,int t,int &cost){
     62     int flow = 0;
     63     cost = 0;
     64     while (spfa(s,t)){
     65         int Min = INF;
     66         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     67             //从最后一个点,向前遍历取最小值
     68             if(Min>edge[i].cap-edge[i].flow)
     69                 Min = edge[i].cap-edge[i].flow;
     70         }
     71         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     72             edge[i].flow+=Min;
     73             edge[i^1].flow-=Min;
     74             cost+=edge[i].cost*Min;
     75         }
     76         flow+=Min;
     77     }
     78     return flow;
     79 }
     80 int main(){
     81     ios::sync_with_stdio(false);
     82     int n;
     83     int a[105];
     84     int sum = 0;
     85     cin>>n;
     86     for(int i=1;i<=n;i++) {
     87         cin >> a[i];
     88         sum+=a[i];
     89     }
     90     sum/=n;
     91     init(n+2);
     92     for(int i=1;i<=n;i++){
     93         if(a[i]>sum){
     94             addEdge(0,i,a[i]-sum,0);
     95         } else if(a[i]<sum){
     96             addEdge(i,n+1,sum-a[i],0);
     97         }
     98         if(i!=n){
     99             addEdge(i,i+1,INF,1);
    100             addEdge(i+1,i,INF,1);
    101         } else{
    102             addEdge(i,1,INF,1);
    103             addEdge(1,i,INF,1);
    104         }
    105     }
    106     int ans = 0;
    107     minCostMaxFlow(0,n+1,ans);
    108     cout<<ans<<endl;
    109 }
    View Code

    3.P4015  运输问题

    费用流,全裸的吧,啊啊啊什么全裸??

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int MAXN = 10000;
      5 const int MAXM = 100000;
      6 const int INF = 0x3f3f3f3f;
      7 int n,m;
      8 struct Edge{
      9     int to,next,cap,flow,cost;
     10 }edge[MAXM];
     11 int head[MAXN],tol;
     12 int pre[MAXN],dis[MAXN];
     13 bool vis[MAXN];
     14 void init(){
     15     tol = 0;
     16     memset(head,-1, sizeof(head));
     17 }
     18 void addEdge(int u,int v,int cap,int cost){
     19     edge[tol].to=v;
     20     edge[tol].cap = cap;
     21     edge[tol].cost = cost;
     22     edge[tol].flow = 0;
     23     edge[tol].next = head[u];
     24     head[u]=tol++;
     25     edge[tol].to = u;
     26     edge[tol].cap = 0;
     27     edge[tol].cost = -cost;
     28     edge[tol].flow = 0;
     29     edge[tol].next = head[v];
     30     head[v]=tol++;
     31 }
     32 bool spfa(int s,int t,int N){
     33     queue<int> q;
     34     for(int i=0;i<N;i++){
     35         dis[i]=INF;
     36         vis[i] = false;
     37         pre[i]=-1;
     38     }
     39     dis[s]=0;
     40     vis[s]=true;
     41     q.push(s);
     42     while (!q.empty()){
     43         int u = q.front();
     44         q.pop();
     45         vis[u] = false;
     46         for(int i=head[u];i!=-1;i=edge[i].next){
     47             int v = edge[i].to;
     48             if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
     49                 dis[v]=dis[u]+edge[i].cost;
     50                 pre[v]=i;
     51                 if(!vis[v]){
     52                     vis[v]=true;
     53                     q.push(v);
     54                 }
     55             }
     56         }
     57     }
     58     if(pre[t]==-1)return false;
     59     return true;
     60 }
     61 ll minCostMaxFlow(int s,int t,ll &cost,int N){
     62     int flow = 0;
     63     cost = 0;
     64     while (spfa(s,t,N)){
     65         int Min = INF;
     66         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     67             if(Min>edge[i].cap-edge[i].flow)
     68                 Min = edge[i].cap-edge[i].flow;
     69         }
     70         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     71             edge[i].flow+=Min;
     72             edge[i^1].flow-=Min;
     73             cost+=1ll*edge[i].cost*Min;
     74         }
     75     }
     76     return flow;
     77 }
     78 
     79 int a[105],b[105],g[105][105];
     80 int main(){
     81     init();
     82     ios::sync_with_stdio(false);
     83     cin>>n>>m;
     84     for(int i=1;i<=n;i++){
     85         cin>>a[i];
     86         addEdge(0,i,a[i],0);
     87     }
     88     for(int i=1;i<=m;i++){
     89         cin>>b[i];
     90         addEdge(i+n,n+m+1,b[i],0);
     91     }
     92     for(int i=1;i<=n;i++){
     93         for(int j=1;j<=m;j++){
     94             cin>>g[i][j];
     95             addEdge(i,j+n,INF,g[i][j]);
     96         }
     97     }
     98     ll cost = 0;
     99     minCostMaxFlow(0,n+m+1,cost,n+m+2);
    100     cout<<cost<<endl;
    101     cost = 0;
    102     init();
    103     for(int i=1;i<=n;i++){
    104         addEdge(0,i,a[i],0);
    105     }
    106     for(int i=1;i<=m;i++){
    107         addEdge(i+n,n+m+1,b[i],0);
    108     }
    109     for(int i=1;i<=n;i++){
    110         for(int j=1;j<=m;j++){
    111             addEdge(i,j+n,INF,-g[i][j]);
    112         }
    113     }
    114     minCostMaxFlow(0,n+m+1,cost,n+m+2);
    115     cout<<-cost<<endl;
    116 }
    View Code

    4. 4014 分配问题

    费用流&二分图完美匹配,只写了费用流的做法,这道题建图也很显然吧。。。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int MAXN = 10000;
      5 const int MAXM = 100000;
      6 const int INF = 0x3f3f3f3f;
      7 struct Edge{
      8     int to,next,cap,flow,cost;
      9 }edge[MAXM];
     10 int head[MAXN],tol;
     11 int pre[MAXN],dis[MAXN];
     12 bool vis[MAXN];
     13 void init(){
     14     tol = 0;
     15     memset(head,-1, sizeof(head));
     16 }
     17 void addEdge(int u,int v,int cap,int cost){
     18     edge[tol].to=v;
     19     edge[tol].cap = cap;
     20     edge[tol].cost = cost;
     21     edge[tol].flow = 0;
     22     edge[tol].next = head[u];
     23     head[u]=tol++;
     24     edge[tol].to = u;
     25     edge[tol].cap = 0;
     26     edge[tol].cost = -cost;
     27     edge[tol].flow = 0;
     28     edge[tol].next = head[v];
     29     head[v]=tol++;
     30 }
     31 bool spfa(int s,int t,int N){
     32     queue<int> q;
     33     for(int i=0;i<N;i++){
     34         dis[i]=INF;
     35         vis[i] = false;
     36         pre[i]=-1;
     37     }
     38     dis[s]=0;
     39     vis[s]=true;
     40     q.push(s);
     41     while (!q.empty()){
     42         int u = q.front();
     43         q.pop();
     44         vis[u] = false;
     45         for(int i=head[u];i!=-1;i=edge[i].next){
     46             int v = edge[i].to;
     47             if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
     48                 dis[v]=dis[u]+edge[i].cost;
     49                 pre[v]=i;
     50                 if(!vis[v]){
     51                     vis[v]=true;
     52                     q.push(v);
     53                 }
     54             }
     55         }
     56     }
     57     if(pre[t]==-1)return false;
     58     return true;
     59 }
     60 ll minCostMaxFlow(int s,int t,ll &cost,int N){
     61     int flow = 0;
     62     cost = 0;
     63     while (spfa(s,t,N)){
     64         int Min = INF;
     65         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     66             if(Min>edge[i].cap-edge[i].flow)
     67                 Min = edge[i].cap-edge[i].flow;
     68         }
     69         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     70             edge[i].flow+=Min;
     71             edge[i^1].flow-=Min;
     72             cost+=1ll*edge[i].cost*Min;
     73         }
     74     }
     75     return flow;
     76 }
     77 int n;
     78 int g[105][105];
     79 int main(){
     80     ios::sync_with_stdio(false);
     81     init();
     82     cin>>n;
     83     for(int i=1;i<=n;i++){
     84         addEdge(0,i,1,0);
     85         for(int j=1;j<=n;j++){
     86             cin>>g[i][j];
     87             addEdge(i,j+n,1,g[i][j]);
     88         }
     89         addEdge(i+n,n+n+1,1,0);
     90     }
     91     ll cost = 0;
     92     minCostMaxFlow(0,n+n+1,cost,n+n+2);
     93     cout<<cost<<endl;
     94     init();
     95     cost=0;
     96     for(int i=1;i<=n;i++){
     97         addEdge(0,i,1,0);
     98         for(int j=1;j<=n;j++){
     99             addEdge(i,j+n,1,-g[i][j]);
    100         }
    101         addEdge(i+n,n+n+1,1,0);
    102     }
    103     minCostMaxFlow(0,n+n+1,cost,n+n+2);
    104     cout<<-cost<<endl;
    105 }
    View Code

    5. 3254 圆桌问题

    最大流,源点到每个单位连人数,每个单位到每个桌子连1,每个桌子到汇点连人数。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 425
     4 #define INF 0x3f3f3f3f
     5 
     6 int e[N][N];
     7 int pre[N]; //记录当前点的前驱。
     8 int d[N];   //记录距离标号  i-t距离的下界。
     9 int num[N];  //gap优化,每个距离下标下的节点编号有多少个,为0的话,说明s-t不连通
    10 int SAP(int s,int t){
    11     memset(pre,-1,sizeof(pre));
    12     memset(d,0,sizeof(d));
    13     memset(num,0,sizeof(num));
    14     num[0]=t;
    15     int v,u=pre[s]=s,flow=0,aug=INF;
    16     while(d[s]<t){  //else 残量网络中不存在s-t路。
    17         //寻找可行弧
    18         for(v=1;v<=t;v++){
    19             if(e[u][v]>0&&d[u]==d[v]+1){
    20                 break;
    21             }
    22         }
    23         if(v<=t){
    24             pre[v]=u;
    25             u=v;
    26             if(v==t){
    27                 aug=INF;
    28                 //寻找当前找到路径上的最大流
    29                 for(int i=v;i!=s;i=pre[i]){
    30                     if(aug>e[pre[i]][i]) aug=e[pre[i]][i];
    31                 }
    32                 flow+=aug;
    33                 //更新残留网络。
    34                 for(int i=v;i!=s;i=pre[i]){
    35                     e[pre[i]][i]-=aug;
    36                     e[i][pre[i]]+=aug;
    37                 }
    38                 u=s;        //从源点开始继续搜。
    39             }
    40         }else{
    41             //找不到可行弧
    42             int minlevel=t;
    43             //寻找与当前点连接的最小的距离标号。
    44             for(v=1;v<=t;v++){
    45                 if(e[u][v]>0&&minlevel>d[v]){
    46                     minlevel=d[v];
    47                 }
    48             }
    49             num[d[u]]--;            //当前标号的数目减一
    50             if(!num[d[u]]) break; //出现断层。
    51             d[u]=minlevel+1;
    52             num[d[u]]++;
    53             u=pre[u];
    54         }
    55     }
    56     return flow;
    57 }
    58 int n,m;
    59 int a[303],b[303];
    60 int main() {
    61     ios::sync_with_stdio(false);
    62     cin>>n>>m;
    63     int sum = 0;
    64     for(int i=1;i<=n;i++){
    65         cin>>a[i];
    66         sum+=a[i];
    67     }
    68     for(int i=1;i<=m;i++){
    69         cin>>b[i];
    70     }
    71     for(int i=2;i<=n+1;i++){
    72         for(int j=1;j<=m;j++){
    73             e[i][j+n+1]=1;
    74         }
    75     }
    76     for(int i=2;i<=n+1;i++){
    77         e[1][i] = a[i-1];
    78     }
    79     for(int i=1;i<=m;i++){
    80         e[i+n+1][n+m+2]=b[i];
    81     }
    82     int flag = SAP(1,n+m+2)==sum;
    83     cout<<flag<<endl;
    84     if(flag){
    85         for(int i=2;i<=n+1;i++){
    86             for(int j=1;j<=m;j++){
    87                 if(e[i][j+n+1]==0){
    88                     cout<<j<<' ';
    89                 }
    90             }
    91             cout<<endl;
    92         }
    93     }
    94 }
    View Code

    6.2774 方格取数

    很显然的最小割,用所有数的和减去最小割就是答案了吧,然后最小割等于最大流。

    我们可以把点按照 (i+j) 的奇偶 分为两类,然后两类之间连边INF,源点到一类点连边权值,另一类到汇点连边权值。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int INF = 0x3f3f3f3f;
     4 struct Edge{
     5     int from,to,cap,flow;//容量流量
     6 };
     7 int n,m,s,t;//节点数,边数,源汇点
     8 vector<Edge> edges;//边表
     9 vector<int> G[35555];//G[i][j]表示结点i的第j条边在e数组中的序号
    10 bool vis[36666];//BFS使用
    11 int d[35555];//分层图
    12 int cur[35555];//当前弧
    13 void addEdge(int from,int to,int cap){
    14     edges.push_back((Edge){from,to,cap,0});
    15     edges.push_back(Edge{to,from,0,0});
    16     m = edges.size();
    17     G[from].push_back(m-2);
    18     G[to].push_back(m-1);
    19 }
    20 bool BFS(){
    21     memset(vis,0, sizeof(vis));
    22     queue<int> Q;
    23     Q.push(s);
    24     d[s]=0;
    25     vis[s]=1;
    26     while (!Q.empty()){
    27         int x = Q.front();
    28         Q.pop();
    29         for(int i=0;i<G[x].size();i++){
    30             Edge &e = edges[G[x][i]];
    31             if(!vis[e.to]&&e.cap>e.flow){
    32                 vis[e.to]=1;
    33                 d[e.to]=d[x]+1;
    34                 Q.push(e.to);
    35             }
    36         }
    37     }
    38     return vis[t];//能否增广到
    39 }
    40 int DFS(int x,int a){
    41     if(x==t||a==0)
    42         return a;
    43     int flow = 0,f;
    44     for(int& i=cur[x];i<G[x].size();i++){//当前弧优化
    45         Edge& e = edges[G[x][i]];
    46         if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
    47             e.flow+=f;
    48             edges[G[x][i]^1].flow-=f;
    49             flow+=f;
    50             a-=f;
    51             if(a==0)//??????炸点优化o.o
    52                 break;
    53         }
    54     }
    55     return flow;
    56 }
    57 int maxflow(){
    58     int flow = 0;
    59     while (BFS()){
    60         memset(cur,0, sizeof(cur));
    61         flow+=DFS(s,INF);
    62     }
    63     return flow;
    64 }
    65 int M,N,g[105][105];
    66 bool in(int x,int y){
    67     return x>=1&&x<=M&&y>=1&&y<=N;
    68 }
    69 int main(){
    70     ios::sync_with_stdio(false);
    71     cin>>M>>N;
    72     int sum = 0;
    73     for(int i=1;i<=M;i++){
    74         for(int j=1;j<=N;j++){
    75             cin>>g[i][j];
    76             sum+=g[i][j];
    77         }
    78     }
    79     for(int i=1;i<=M;i++){
    80         for(int j=1;j<=N;j++){
    81             if((i+j)&1){
    82                 addEdge(0,(i-1)*N+j,g[i][j]);
    83                 if(in(i-1,j))
    84                     addEdge((i-1)*N+j,(i-2)*N+j,INF);
    85                 if(in(i+1,j))
    86                     addEdge((i-1)*N+j,i*N+j,INF);
    87                 if(in(i,j-1))
    88                     addEdge((i-1)*N+j,(i-1)*N+j-1,INF);
    89                 if(in(i,j+1))
    90                     addEdge((i-1)*N+j,(i-1)*N+j+1,INF);
    91             } else{
    92                 addEdge((i-1)*N+j,N*M+1,g[i][j]);
    93             }
    94         }
    95     }
    96     n=N*M+2,s=0,t=N*M+1;
    97     cout<<sum-maxflow()<<endl;
    98 }
    View Code

    7. 2763 试题库问题

    这道题非常的水啊,我刚才写了写一遍就过了。

    最大流,建图请看代码qwq

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int MAXN = 2010;
      4 const int MAXM = 66666;
      5 const int INF = 0x3f3f3f3f;
      6 struct Edge{
      7     int to,next,cap,flow;
      8 }edge[MAXM];
      9 int tol;
     10 int head[MAXN];
     11 void init(){
     12     tol = 2;
     13     memset(head,-1, sizeof(head));
     14 }
     15 void addEdge(int u,int v,int w,int rw = 0){
     16     edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
     17     edge[tol].next=head[u];head[u]=tol++;
     18     edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
     19     edge[tol].next=head[v];head[v]=tol++;
     20 }
     21 int Q[MAXN];
     22 int dep[MAXN],cur[MAXN],sta[MAXN];
     23 bool bfs(int s,int t,int n){
     24     int front = 0,tail = 0;
     25     memset(dep,-1, sizeof(dep[0])*(n+1));
     26     dep[s]=0;
     27     Q[tail++] = s;
     28     while (front<tail){
     29         int u = Q[front++];
     30         for(int i=head[u];i!=-1;i=edge[i].next){
     31             int v = edge[i].to;
     32             if(edge[i].cap>edge[i].flow&&dep[v]==-1){
     33                 dep[v]=dep[u]+1;
     34                 if(v==t)return true;
     35                 Q[tail++] = v;
     36             }
     37         }
     38     }
     39     return false ;
     40 }
     41 int dinic(int s,int t,int n){
     42     int maxflow = 0;
     43     while (bfs(s,t,n)){
     44         for(int i=0;i<n;i++)cur[i] = head[i];
     45         int u = s,tail = 0;
     46         while (cur[s]!=-1){
     47             if(u==t){
     48                 int tp = INF;
     49                 for(int i=tail-1;i>=0;i--){
     50                     tp = min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
     51                 }
     52                 maxflow +=tp;
     53                 for(int i=tail-1;i>=0;i--){
     54                     edge[sta[i]].flow+=tp;
     55                     edge[sta[i]^1].flow-=tp;
     56                     if(edge[sta[i]].cap-edge[sta[i]].flow==0)
     57                         tail = i;
     58                 }
     59                 u=edge[sta[tail]^1].to;
     60             }
     61             else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
     62                 sta[tail++]=cur[u];
     63                 u = edge[cur[u]].to;
     64             }
     65             else{
     66                 while (u!=s&&cur[u]==-1)
     67                     u = edge[sta[--tail]^1].to;
     68                 cur[u] = edge[cur[u]].next;
     69             }
     70         }
     71     }
     72     return maxflow;
     73 }
     74 int k,n,a,b,sum;
     75 int main(){
     76     ios::sync_with_stdio(false);
     77     init();
     78     cin>>k>>n;
     79     for(int i=1;i<=k;i++){
     80         cin>>a;
     81         sum+=a;
     82         addEdge(i+n,k+n+1,a);
     83     }
     84     for(int i=1;i<=n;i++){
     85         addEdge(0,i,1);
     86         cin>>a;
     87         while (a--){
     88            cin>>b;
     89            //v[i].push_back(b);
     90            addEdge(i,b+n,1);
     91         }
     92     }
     93     int ans = dinic(0,k+n+1,k+n+2);
     94     if(ans!=sum){
     95         cout<<"No Solution!"<<endl;
     96     } else{
     97         for(int i=1;i<=k;i++){
     98             cout<<i<<": ";
     99             int tmp = i+n;
    100             for(int j=head[tmp];j!=-1;j=edge[j].next){
    101                 if(edge[j^1].flow==1)
    102                     cout<<edge[j].to<<' ';
    103             }
    104             cout<<endl;
    105         }
    106     }
    107 }
    View Code

    8. 2764 最小路径覆盖问题

    拆点就行,然后跑二分图匹配&最大流,每匹配到一个就意味着有两个点可以连在一条边上吧,所以答案就是总的减去匹配数,详细的可以去看hzw的blog,顺便%hzw

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int n,m,a,b;
     4 const int MAXN= 305;
     5 int g[MAXN][MAXN];
     6 int linker[MAXN],used[MAXN];
     7 int vis[MAXN];
     8 vector<int> ans;
     9 bool dfs(int u){
    10     for (int v = 1;v<=2*n;v++){
    11         if(g[u][v]&&!used[v]) {
    12             used[v] = true;
    13             if (linker[v] == -1 || dfs(linker[v])) {
    14                 linker[v] = u;
    15                 return true;
    16             }
    17         }
    18     }
    19     return false;
    20 }
    21 int hungary(){
    22     int res = 0;
    23     memset(linker,-1, sizeof(linker));
    24     for(int u=1;u<=n;u++){
    25         memset(used,0, sizeof(used));
    26         if (dfs(u))
    27             res++;
    28     }
    29     return res;
    30 }
    31 int main(){
    32     ios::sync_with_stdio(false);
    33     cin>>n>>m;
    34     while (m--){
    35         cin>>a>>b;
    36         g[a][b+n]=1;
    37     }
    38     int res = hungary();
    39     for(int i=2*n;i>n;i--){
    40         //cout<<linker[i]<<' ';
    41         if(vis[i])
    42             continue;
    43         int tmp = i;
    44         while (tmp!=n-1){
    45             ans.push_back(tmp-n);
    46             tmp=linker[tmp]+n;
    47             vis[tmp]=1;
    48         }
    49         reverse(ans.begin(),ans.end());
    50         for(int j=0;j<ans.size();j++)
    51             cout<<ans[j]<<' ';
    52         cout<<endl;
    53         ans.clear();
    54     }
    55     cout<<n-res<<endl;
    56 }
    View Code

    9.牛客国庆day6A题(乱入

    大水题,题解说的什么乱七八咋的(逃

    一共n+m+2个点就可以,然后连边就是13579这样子。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int MAXN = 10000;
      5 const int MAXM = 100000;
      6 const int INF = 0x3f3f3f3f;
      7 struct Edge{
      8     int to,next,cap,flow,cost;
      9 }edge[MAXM];
     10 int head[MAXN],tol;
     11 int pre[MAXN],dis[MAXN];
     12 bool vis[MAXN];
     13 void init(){
     14     tol = 0;
     15     memset(head,-1, sizeof(head));
     16 }
     17 void addEdge(int u,int v,int cap,int cost){
     18     edge[tol].to=v;
     19     edge[tol].cap = cap;
     20     edge[tol].cost = cost;
     21     edge[tol].flow = 0;
     22     edge[tol].next = head[u];
     23     head[u]=tol++;
     24     edge[tol].to = u;
     25     edge[tol].cap = 0;
     26     edge[tol].cost = -cost;
     27     edge[tol].flow = 0;
     28     edge[tol].next = head[v];
     29     head[v]=tol++;
     30 }
     31 bool spfa(int s,int t,int N){
     32     queue<int> q;
     33     for(int i=0;i<N;i++){
     34         dis[i]=INF;
     35         vis[i] = false;
     36         pre[i]=-1;
     37     }
     38     dis[s]=0;
     39     vis[s]=true;
     40     q.push(s);
     41     while (!q.empty()){
     42         int u = q.front();
     43         q.pop();
     44         vis[u] = false;
     45         for(int i=head[u];i!=-1;i=edge[i].next){
     46             int v = edge[i].to;
     47             if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
     48                 dis[v]=dis[u]+edge[i].cost;
     49                 pre[v]=i;
     50                 if(!vis[v]){
     51                     vis[v]=true;
     52                     q.push(v);
     53                 }
     54             }
     55         }
     56     }
     57     if(pre[t]==-1)return false;
     58     return true;
     59 }
     60 ll minCostMaxFlow(int s,int t,ll &cost,int N){
     61     int flow = 0;
     62     cost = 0;
     63     while (spfa(s,t,N)){
     64         int Min = INF;
     65         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     66             if(Min>edge[i].cap-edge[i].flow)
     67                 Min = edge[i].cap-edge[i].flow;
     68         }
     69         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     70             edge[i].flow+=Min;
     71             edge[i^1].flow-=Min;
     72             cost+=1ll*edge[i].cost*Min;
     73         }
     74         flow+=Min;
     75     }
     76     return flow;
     77 }
     78 int n,m;
     79 int main(){
     80     ios::sync_with_stdio(false);
     81     init();
     82     cin>>n>>m;
     83     int a,b;
     84     for(int i=1;i<=n;i++){
     85         cin>>a>>b;
     86         addEdge(i,a+n,1,0);
     87         addEdge(i,b+n,1,0);
     88     }
     89     for(int i=1;i<=n;i++){
     90         addEdge(0,i,1,0);
     91     }
     92     for(int i=n+1;i<=n+m;i++){
     93         for(int j=1;j<=n;j++){
     94             addEdge(i,n+m+1,1,2*j-1);
     95         }
     96     }
     97     ll cost = 0;
     98     minCostMaxFlow(0,n+m+1,cost,n+m+2);
     99     cout<<cost<<endl;
    100 }
    View Code

    唔然后剩下的全咕着,应该要等这个赛季结束之后,顺便我去的北京,祝自己rp++;

  • 相关阅读:
    Python randrange() 函数
    200行Python代码实现2048
    select默认下拉箭头改变、option样式清除
    图片垂直居中
    去除select边框和三角-----appearance:none
    原生 js 实现点击按钮复制文本
    This dependency was not found: * !!vue-style-loader!css-loader?……解决方案
    vue项目启动时将localhost替换成指定ip地址
    安装cnpm
    vue 项目要使用的库
  • 原文地址:https://www.cnblogs.com/MXang/p/9711300.html
Copyright © 2020-2023  润新知