[AYYZVijos1761]运输问题

水水水……放一下模版就好了:

  1 /*
  2     P1761 运输问题
  3     一般增广路算法
  4     Author:GodCowC 
  5 */
  6 #include <iostream>
  7 #include <cstdio>
  8 #include <cctype>
  9 #include <cmath>
 10 #define MAXN 101
 11 #define INF 100000000
 12 using namespace std;
 13 int readint()                    
 14 {
 15     int ans=0;
 16     char c;
 17     while (!isdigit(c=getchar()));
 18     do
 19     {
 20         ans=ans*10+c-'0';
 21         c=getchar();    
 22     } while (isdigit(c));
 23     return ans;
 24 }
 25 int n;                                
 26 int s,t;                        
 27 struct Node                             
 28 {
 29     int pre;                    
 30     bool del;                    
 31     Node(int p=0,bool d=false):pre(p),del(d){}
 32 };
 33 struct Edge                        
 34 {
 35     int flow,cap;                
 36     Edge(int f=0,int c=0):flow(f),cap(c){}
 37 };
 38 Node argpath[MAXN];
 39 Edge graph[MAXN][MAXN];
 40 void init()
 41 {
 42     for (int i=1;i<=n;i++)
 43         argpath[i]=Node(0,0);
 44 }
 45 int find()
 46 {
 47     int i(s);
 48     while (i<=n && (!argpath[i].pre || argpath[i].del))
 49         i++;
 50     return (i>n?0:i);
 51 }
 52 bool ford(int& change)
 53 {
 54     init();
 55     argpath[s].pre=s;
 56     do
 57     {
 58         int i=find();
 59         if (!i)
 60             return true;
 61         for (int j=1;j<=n;j++)
 62         {
 63             if (argpath[j].pre)
 64                 continue;
 65             argpath[j].pre=(graph[i][j].flow<graph[i][j].cap?i:argpath[j].pre);
 66             argpath[j].pre=(graph[j][i].flow?-i:argpath[j].pre);
 67         }
 68         argpath[i].del=true;
 69     } while (!argpath[t].pre);
 70     int now=t;
 71     change=INF;
 72     do
 73     {
 74         int j=now;
 75         now=abs(argpath[j].pre);
 76         change=min(change,
 77             (argpath[j].pre<0?graph[j][now].flow:graph[now][j].cap-graph[now][j].flow));
 78     } while (now!=s);
 79     return false;
 80 }
 81 void fulkerson(int change)
 82 {
 83     int now=t;
 84     do
 85     {
 86         int j=now;
 87         now=abs(argpath[j].pre);
 88         if (argpath[j].pre<0)
 89             graph[j][now].flow-=change;
 90         else
 91             graph[now][j].flow+=change;
 92     } while (now!=s);
 93 }
 94 void putmaxflow()
 95 {
 96     int ans=0;
 97     for (int i=1;i<=n;i++)
 98         ans+=graph[i][t].flow;
 99     cout<<ans<<endl;
100 }
101 int main()
102 {
103     n=readint();
104     s=1,t=n;
105     for (int i=1;i<=n;i++)
106         for (int j=1;j<=n;j++)
107             graph[i][j]=Edge(0,readint());
108     do
109     {
110         int change=0;                
111         bool ok=ford(change);     
112         if (ok)                    
113         {
114             putmaxflow();
115             break;        
116         }
117         else
118             fulkerson(change);
119     } while (true);
120     return 0;
121 }
一般增广路算法
  1 /*
  2     P1761 运输问题
  3     预流推进算法
  4     Author:GodCowC 
  5 */
  6 #include <iostream>
  7 #include <cstdio>
  8 #include <cctype>
  9 #include <cmath>
 10 #include <algorithm>
 11 #define MAXN 101
 12 #define INF 100000000
 13 using namespace std;
 14 int readint()                    
 15 {
 16     int ans=0;
 17     char c;
 18     while (!isdigit(c=getchar()));
 19     do
 20     {
 21         ans=ans*10+c-'0';
 22         c=getchar();    
 23     } while (isdigit(c));
 24     return ans;
 25 }
 26 int n,d[MAXN],e[MAXN],s,t;
 27 int c[MAXN][MAXN],p[MAXN][MAXN];
 28 int check()
 29 {
 30     int j=0;
 31     for (int i=2;i<n;i++)
 32         j+=e[i];
 33     return j;
 34 }
 35 int find()
 36 {
 37     for (int i=2;i<n;i++)
 38         if (e[i]!=0)
 39             return i;
 40 }
 41 int push(int x)
 42 {
 43     int i,j;
 44     for (i=1;i<=n;i++)
 45         if (d[x]==d[i]+1 && c[x][i]!=0)
 46             break;
 47     if (i<=n)
 48     {
 49         j=min(e[x],c[x][i]);
 50         e[x]-=j;
 51         c[x][i]-=j;
 52         if (i!=t)
 53             e[i]+=j;
 54         c[i][x]+=j;
 55     }
 56     else
 57         d[x]++;
 58     if (j==0)
 59         d[x]++;
 60     return 0;
 61 }
 62 int main()
 63 {
 64     int sum=0;
 65     n=readint();
 66     for (int i=1;i<=n;i++)
 67         for (int j=1;j<=n;j++)
 68             c[i][j]=readint();
 69     for (int i=1;i<=n;i++)
 70         for (int j=1;j<=n;j++)
 71         {
 72             if (c[i][j]>0)
 73                 p[i][j]=1;
 74             else if (i==j)
 75                 p[i][j]=0;
 76             else
 77                 p[i][j]=32767;
 78         }
 79     for (int k=1;k<=n;k++)
 80         for (int i=1;i<=n;i++)
 81             for (int j=1;j<=n;j++)
 82                     p[i][j]=min(p[i][j],p[i][k]+p[k][j]);
 83     s=1,t=n;
 84     for (int i=1;i<=n;i++)
 85         d[i]=p[i][t];
 86     for (int i=1;i<=n;i++)
 87     {
 88         e[i]=c[s][i];
 89         sum+=e[i];
 90         c[i][s]=c[s][i];
 91     }
 92     d[s]=n;
 93     while (check())
 94     {
 95         int i=find();
 96         push(i);
 97     }
 98     cout<<sum-e[s]<<endl;
 99     return 0;
100 } 
预流推进算法

 

转载于:https://www.cnblogs.com/changke/p/5011476.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值