zoukankan      html  css  js  c++  java
  • POJ 2455 Secret Milking Machine (二分 + 最大流)

    题目大意:

    给出一张无向图,找出T条从1..N的路径,互不重复,求走过的所有边中的最大值最小是多少。

    算法讨论:

    首先最大值最小就提醒我们用二分,每次二分一个最大值,然后重新构图,把那些边权符合要求的边加入新图,在新图上跑网络流。

    这题有许多注意的地方:

    1、因为是无向图,所以我们在加正向边和反向边的时候,流量都是1,而不是正向边是1,反向边是0。

    2、题目中说这样的路径可能不止t条,所以我们在最后二分判定的时候不能写 == t,而是要 >= t。

    3、这题很容易T ,表示我T了N遍,弱菜啊。

    Codes:

      1 #include <cstring>
      2 #include <cstdlib>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cstdio>
      6 #include <vector>
      7 #include <queue>
      8 
      9 using namespace std;
     10 
     11 struct Edge{
     12     int from, to, cap, flow;
     13     Edge(int _from = 0, int _to = 0, int _cap = 0, int _flow = 0): 
     14         from(_from), to(_to), cap(_cap), flow(_flow) {}
     15 }E[40000 + 5];
     16 
     17 struct Dinic{
     18     static const int N = 200 + 5;
     19     static const int M = 80000 + 5; 
     20     static const int oo = 0x3f3f3f3f;
     21     
     22     int n, m, s, t;
     23     vector <Edge> edges;
     24     vector <int> G[N];
     25     int dis[N], cur[N];
     26     bool vi[N];
     27     
     28     void Clear(){
     29         for(int i = 1; i <= n; ++ i) G[i].clear();
     30         edges.clear();
     31     }
     32     
     33     void Add(int from, int to, int cap, int flow){
     34         edges.push_back((Edge){from, to, cap, 0});
     35         edges.push_back((Edge){to, from, cap, 0});
     36         int m = edges.size();
     37         G[from].push_back(m - 2);
     38         G[to].push_back(m - 1);
     39     }
     40     
     41     bool bfs(){
     42         for(int i = 1; i <= n; ++ i) vi[i] = false;
     43         dis[s] = 0; vi[s] = true;
     44         queue <int> q; q.push(s);
     45         
     46         while(!q.empty()){
     47             int x = q.front(); q.pop();
     48             for(int i = 0; i < G[x].size(); ++ i){
     49                 Edge &e = edges[G[x][i]];
     50                 if(!vi[e.to] && e.cap > e.flow){
     51                     vi[e.to] = true;
     52                     dis[e.to] = dis[x] + 1;
     53                     q.push(e.to);
     54                 }
     55             }
     56         }
     57         return vi[t];
     58     }
     59     
     60     int dfs(int x, int a){
     61         if(x == t || a == 0) return a;
     62         int flw = 0, f;
     63         for(int &i = cur[x]; i < G[x].size(); ++ i){
     64             Edge &e = edges[G[x][i]];
     65             if(dis[x] + 1 == dis[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0){
     66                 e.flow += f; edges[G[x][i]^1].flow -= f;
     67                 a -= f; flw += f;
     68                 if(!a) break;
     69             }
     70         }
     71         return flw;
     72     }
     73     
     74     int Maxflow(int s, int t){
     75         this->s = s;this-> t = t;
     76         int flw = 0;
     77         while(bfs()){
     78             memset(cur, 0, sizeof cur);
     79             flw += dfs(s, oo);
     80         }
     81         return flw;
     82     }
     83     
     84 }Net;
     85 
     86 int ns, ps, ts;
     87 int l = 0x3f3f3f3f, r, mid;
     88 
     89 bool check(int mv){
     90     for(int i = 0; i < ps; ++ i){
     91         if(E[i].cap <= mv){
     92             Net.Add(E[i].from, E[i].to, 1, 0);
     93         }
     94     }
     95     return Net.Maxflow(1, Net.n) >= ts;
     96 }
     97 
     98 int Solve(){
     99     int ans;
    100     
    101     while(l <= r){
    102         Net.Clear();
    103         mid = l + (r - l) / 2;    
    104         if(check(mid)){
    105             ans = mid; r = mid - 1;
    106         }
    107         else l = mid + 1;
    108     }
    109     
    110     return ans;
    111 }
    112 
    113 int main(){
    114     int x, y, z;
    115     
    116     scanf("%d%d%d", &ns, &ps, &ts);
    117     Net.n = ns;
    118     for(int i = 0; i < ps; ++ i){
    119         scanf("%d%d%d", &x, &y, &z);
    120         E[i] = (Edge){x, y, z, 0};
    121         l = min(l, z); r = max(r, z);
    122     }
    123     
    124     printf("%d
    ", Solve());
    125     return 0;
    126 }
    POJ 2455

    让人更加不能理解的是,为什么我换了上面的邻接表的形式,用STL容器来存邻接表就AC,用数组来存就T成狗。

    下面是我狂T的代码,良心网友们给查查错误呗。

      1 #include <cstdio>
      2     #include <iostream>
      3     #include <cstring>
      4     #include <cstdlib>
      5     #include <algorithm>
      6     #include <queue>
      7     
      8     using namespace std;
      9     
     10     int ns, ps, ts, te;
     11     int l=0x3f3f3f3f, r, Mid;
     12     
     13     struct Edge{
     14         int from, to, dt;
     15     }e[40000 + 5];
     16     
     17     struct Dinic{
     18       static const int maxn = 300 + 5;
     19       static const int maxm = 80000 + 5;
     20       static const int oo = 0x3f3f3f3f;
     21       
     22       int n,m,s,t;
     23       int tot;
     24       int first[maxn],next[maxm];
     25       int u[maxm],v[maxm],cap[maxm],flow[maxm];
     26       int cur[maxn],dis[maxn];
     27       bool vi[maxn];
     28       
     29       Dinic(){tot=0;memset(first,-1,sizeof first);}
     30       void Clear(){tot = 0;memset(first,-1,sizeof first);}
     31       void Add(int from,int to,int cp,int flw){
     32           u[tot] = from;v[tot] = to;cap[tot] = cp;flow[tot] = 0;
     33           next[tot] = first[u[tot]];
     34           first[u[tot]] = tot;
     35           ++ tot;
     36       }
     37       bool bfs(){
     38           memset(vi,false,sizeof vi);
     39           queue <int> q;
     40           dis[s] = 0;vi[s] = true;
     41           q.push(s);
     42           
     43           while(!q.empty()){
     44           int now = q.front();q.pop();
     45           for(int i = first[now];i != -1;i = next[i]){
     46               if(!vi[v[i]] && cap[i] > flow[i]){
     47               vi[v[i]] = true;
     48               dis[v[i]] = dis[now] + 1;
     49               q.push(v[i]);
     50             }
     51           }
     52         }
     53         return vi[t];
     54       }
     55       int dfs(int x,int a){
     56           if(x == t || a == 0) return a;
     57           int flw=0,f;
     58           int &i = cur[x];
     59           for(i = first[x];i != -1;i = next[i]){
     60             if(dis[x] + 1 == dis[v[i]] && (f = dfs(v[i],min(a,cap[i]-flow[i]))) > 0){
     61               flow[i] += f;flow[i^1] -= f;
     62             a -= f;flw += f;
     63             if(a == 0) break;    
     64           }
     65         }
     66         return flw;
     67       }
     68       int MaxFlow(int s,int t){
     69           this->s = s;this->t = t;
     70           int flw=0;
     71           while(bfs()){
     72             memset(cur,0,sizeof cur);
     73           flw += dfs(s,oo);    
     74         }
     75         return flw;
     76       }
     77     }Net;
     78     
     79     bool check(int mid){
     80         Net.Clear();
     81         for(int i = 1; i <= ps; ++ i){
     82             if(e[i].dt <= mid){
     83                 Net.Add(e[i].from, e[i].to, 1, 0);
     84                 Net.Add(e[i].to, e[i].from, 1, 0);
     85             }
     86         }
     87         return Net.MaxFlow(1, Net.n) >= ts;
     88     }
     89     int Solve(){
     90         int ans;
     91         while(l <= r){
     92             Mid = l + (r - l) / 2;
     93             if(check(Mid)){
     94                 ans = Mid; r = Mid - 1;
     95             }
     96             else l = Mid + 1;
     97         }
     98         return ans;
     99     }
    100     int main(){
    101         int x, y, z;
    102         scanf("%d%d%d", &ns, &ps, &ts);
    103         Net.n = ns;te = 0;
    104         for(int i = 1; i <= ps; ++ i){
    105             scanf("%d%d%d", &x, &y, &z);
    106             ++ te;
    107             e[te].from = x;e[te].to = y;e[te].dt = z;
    108             l = min(l, z); r = max(z, r);
    109         }
    110         printf("%d
    ", Solve());    
    111         return 0;
    112     }
    POJ 2455 T 版
  • 相关阅读:
    Oracle之表空间
    Oracle 数据库实现数据更新:update、merge
    union和union all用法
    SQL Server 使用游标更新数据库中的数据(使用存储过程)
    MDX函数(官方顺序,带示例)
    开窗函数 --over()
    MySql安装与MySQL添加用户、删除用户与授权
    samba服务
    asp.net core系列 58 IS4 基于浏览器的JavaScript客户端应用程序
    asp.net core系列 57 IS4 使用混合流(OIDC+OAuth2.0)添加API访问
  • 原文地址:https://www.cnblogs.com/sxprovence/p/5111871.html
Copyright © 2011-2022 走看看