poj 3228(二分+最大流)

题目链接:http://poj.org/problem?id=3228

思路:增设一个超级源点和一个超级汇点,源点与每一个gold相连,容量为gold数量,汇点与仓库相连,容量为仓库的容量,然后就是二分最小的最大相邻距离,跑最大流验证即可。最大流用的是别人的Dinic模版。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 #define MAXN 222
  8 #define inf 1<<30
  9 
 10 int vs,vt;
 11 int dep[MAXN];
 12 int map[MAXN][MAXN];
 13 
 14 int gold[MAXN],store[MAXN];
 15 int dist[MAXN][MAXN];
 16 void Build_Map(int limit,int n)
 17 {
 18     memset(map,0,sizeof(map));
 19     for(int i=1;i<=n;i++)
 20         for(int j=1;j<=n;j++)
 21             if(dist[i][j]<=limit)map[i][j]=inf;
 22     for(int i=1;i<=n;i++){
 23         map[vs][i]=gold[i];
 24         map[i][vt]=store[i];
 25     }
 26 }
 27 
 28 int BFS(){
 29     queue<int> q;
 30     while(!q.empty())
 31         q.pop();
 32     memset(dep,-1,sizeof(dep));
 33     dep[vs]=0;
 34     q.push(vs);
 35     while(!q.empty()){
 36         int u=q.front();
 37         q.pop();
 38         for(int v=vs;v<=vt;v++)
 39             if(map[u][v]>0 && dep[v]==-1){
 40                 dep[v]=dep[u]+1;
 41                 q.push(v);
 42             }
 43     }
 44     return dep[vt]!=-1;
 45 }
 46 
 47 int DFS(int u,int minx){
 48     if(u==vt)
 49         return minx;
 50     int tmp;
 51     for(int v=vs;v<=vt;v++)
 52         if(map[u][v]>0 && dep[v]==dep[u]+1 && (tmp=DFS(v,min(minx,map[u][v])))){
 53             map[u][v]-=tmp;
 54             map[v][u]+=tmp;
 55             return tmp;
 56         }
 57     dep[u]=-1;
 58     return 0;
 59 }
 60 
 61 int Dinic(){
 62     int ans=0,tmp;
 63     while(BFS()){
 64         while(1){
 65             tmp=DFS(vs,inf);
 66             if(tmp==0)
 67                 break;
 68             ans+=tmp;
 69         }
 70     }
 71     return ans;
 72 }
 73 
 74 int main()
 75 {
 76     int total,n,m,a,b,c;
 77     while(~scanf("%d",&n)){
 78         if(n==0)break;
 79         total=0,vs=0,vt=n+1;
 80         for(int i=1;i<=n;i++)
 81             for(int j=1;j<=n;j++)
 82                 dist[i][j]=inf;
 83         for(int i=1;i<=n;i++){
 84             scanf("%d",&gold[i]);
 85             total+=gold[i];
 86         }
 87         for(int i=1;i<=n;i++)scanf("%d",&store[i]);
 88         scanf("%d",&m);
 89         while(m--){
 90             scanf("%d%d%d",&a,&b,&c);
 91             dist[a][b]=dist[b][a]=c;
 92         }
 93         
 94         int low=0,high=100010,mid,ans=-1;
 95         while(low<=high){
 96             mid=(low+high)>>1;
 97             Build_Map(mid,n);
 98             if(Dinic()==total){
 99                 ans=mid;
100                 high=mid-1;
101             }else 
102                 low=mid+1;
103         }
104         if(ans==-1){
105             printf("No Solution\n");
106         }else 
107             printf("%d\n",ans);
108     }
109     return 0;
110 }
111 
112 
113         
View Code

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值