hdu 4289 Control (最大流 最小割 成都赛区 网络赛)

http://acm.hdu.edu.cn/showproblem.php?pid=4289


题意: 有n个城市,有个小偷想从其中一个城市逃到另一个城市,警察想要堵截这个小偷,知道了在每个城市堵截的成本,问如何安排在哪些城市堵截可以使得

          小偷一定会被抓住,而且成本最低。

题解 : 最大流 ; 将每一个点 查分成两个  ,x 和x+n  他们之间的流量为 在 x 点的花费  ,对于 右边相连的x,y   l连接 x +n  到 y 和 y +n到  x   流量值 为 inf ,(这样保证了  流量 只受拆点边的限制)  最后 求  s  到  e+n 的 最值 即可

dinic  算法:

  1 #include<cstdio>
  2  #include<cstring>
  3  #include<cmath>
  4  #include<iostream>
  5  #include<algorithm>
  6  #include< set>
  7  #include<map>
  8  #include<queue>
  9  #include<vector>
 10  #include< string>
 11  #define INF 0x7fffffff
 12  #define F(x) (x)
 13  #define N(x) (205+(x))
 14  #define CPN(x) (410+(x))
 15  #define D(x) (615+(x))
 16  #define maxn 420
 17  #define CL(a,b) memset(a,b,sizeof(a))
 18 
 19  using  namespace std;
 20 
 21   int next[maxn],dis[maxn];
 22   int s,e;
 23   int  n, m,cnt,a[maxn];
 24   struct node
 25  {
 26       int to;
 27       int cap ;
 28       int next ;
 29  }p[ 200000] ;
 30   void add( int x, int y, int cap)
 31  {
 32      p[cnt].to = y;
 33      p[cnt].cap = cap ;
 34      p[cnt].next = next[x];
 35      next[x] = cnt++ ;
 36 
 37      p[cnt].to = x;
 38      p[cnt].cap =  0;
 39      p[cnt].next = next[y];
 40      next[y] = cnt++ ;
 41  }
 42   int bfs() //  重新 建 图 (按 层数 建图)
 43   {
 44 
 45      memset(dis,- 1, sizeof(dis)) ;
 46      dis[s] =  0 ;
 47      queue< int>que;
 48      que.push(s);
 49 
 50       while(!que.empty())
 51      {
 52 
 53 
 54           int  k = que.front();que.pop() ;
 55           forint i = next[k];i!=- 1;i = p[i].next)
 56          {
 57               int v = p[i].to;
 58 
 59 
 60               int cap = p[i].cap ;
 61 
 62               if(cap >  0 && dis[v] <  0 ) //  如果 可以  可以到达 但 还没有 访问
 63               {
 64 
 65                  dis[v] = dis[k]+  1 ;
 66                  que.push(v) ;
 67              }
 68          }
 69 
 70      }
 71 
 72 
 73       if(dis[e] >  0return  1;
 74       else  return   0 ;
 75 
 76  }
 77 
 78 
 79 
 80   int  dfs( int x, int mx) //  查找  路径上的 最小 的 流量
 81   {
 82 
 83       int i , a ,tf =   0;
 84 
 85       if(x == e)  return mx ;
 86 
 87       for(i = next[x];i!= -  1;i = p[i].next)
 88      {
 89           int v = p[i].to ;
 90           int cap = p[i].cap ;
 91           if(cap >  0 && dis[v] == dis[x] +  1  && (a =dfs(v,min(cap,mx))))
 92          {
 93 
 94              p[i].cap -= a;
 95              p[i^ 1].cap += a;
 96 
 97                 return a;
 98 
 99 
100          }
101      }
102       if(!tf) dis[x] = - 1; //  没有 找到 最小流量 ,说明 从这个点到不了 终点 ,所以  标记一下
103        return tf ;
104  }
105 
106 
107 
108 
109 
110   int main()
111  {
112      int i , j ,x,y;
113      int a;
114       // freopen("data.txt","r",stdin) ;
115       while(scanf( " %d%d%d%d ",&n,&m,&s,&e)!=EOF)
116     {
117 
118         CL(next,- 1) ;
119         cnt =  0;
120         //  scanf("%d%d",&s,&e);
121           for(i =  1 ; i <= n;i++)
122         {
123              scanf( " %d ",&a) ;
124               add(i,i+n,a);
125         }
126 
127 
128           for(i =  0 ;i< m;i++)
129          {
130              scanf( " %d%d ",&x,&y);
131 
132              add(x+n,y,INF) ;
133              add(y + n ,x,INF) ;
134          }
135 
136         e = e + n;
137 
138 
139         int ans =  0;
140         int res;
141 
142         while(bfs())
143        {
144 
145 
146            while(res = dfs(s,INF)) ans+= res ;
147 
148        }
149        printf( " %d\n ",ans);
150     }
151  }

 isap 算法:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include< set>
  7 #include<map>
  8 #include<queue>
  9 #include<vector>
 10 #include< string>
 11  #define INF 0x7fffffff
 12  #define maxn 500
 13  #define CL(a,b) memset(a,b,sizeof(a))
 14 
 15  using  namespace std;
 16  struct node
 17 {
 18      int to;
 19      int cap;
 20      int  next;
 21 }p[ 200000] ;
 22  int dis[maxn],gap[maxn] ,cnt,next[maxn],s,e;
 23  int  n , m,NN ; // NN 为  加完点 之后的 总结点数
 24  void add( int  from, int to, int cap) // 加 的 是 有向边 
 25  {
 26     p[cnt].to = to;
 27     p[cnt].cap = cap ;
 28     p[cnt].next = next[ from];
 29     next[ from] = cnt++;
 30 
 31     p[cnt].to =  from;
 32     p[cnt].cap =  0;
 33     p[cnt].next = next[to];
 34     next[to] = cnt++ ;
 35 }
 36  int dfs( int pos, int cost)
 37 {
 38 
 39      if(pos == e)
 40       return cost ;
 41 
 42      int i,j ,mdis = NN ,f = cost ;
 43 
 44      for(i =  next[pos];i != -  1; i = p[i].next)
 45     {
 46          int to = p[i].to ;
 47          int cap = p[i].cap ;
 48          if(cap >  0 )
 49         {
 50              if(dis[to] +  1 == dis[pos])
 51             {
 52 
 53 
 54                int d = min(f,cap) ; //  注意 这 为 剩余 流量 和 cap 的 最小值
 55 
 56               d = dfs(to,d) ;
 57               p[i].cap -=d;
 58               p[i^ 1].cap +=d;
 59               f -= d;
 60 
 61                if(dis[s] >= NN)   return cost - f; //  如果没有 了 增广路经 结束算法
 62                 if(f ==  0break ;
 63             }
 64              if( dis[to] < mdis ) mdis = dis[to] ; //  记录可扩展的最小的狐
 65 
 66         }
 67 
 68     }
 69      if(f == cost) //   没有 可以 扩展的点
 70      {
 71         --gap[dis[pos]];
 72          if(gap[dis[pos]] ==  0)dis[s] = NN; //  注意这 ,若 距离 为 dis[pos] 这一层都没有 扩展点了(断层) dis[s] = n
 73 
 74         dis[pos] = mdis +  1;
 75 
 76         ++gap[dis[pos]] ;
 77     }
 78      return cost  - f ;
 79 }
 80  int isap(  int b, int t)
 81 {
 82 
 83      int ret =   0;
 84     s = b;
 85     e = t;
 86     CL(gap, 0);
 87     CL(dis, 0) ;
 88     gap[ 0] = NN ;
 89      while(dis[s] < NN)
 90     {
 91         ret+=dfs(s,INF) ;
 92     }
 93      return ret ;
 94 
 95 }
 96  int main()
 97 {
 98      int  i,x,y,a,b,t;
 99      // freopen("data.txt","r",stdin) ;
100       while(scanf( " %d%d%d%d ",&n,&m,&b,&t)!=EOF)
101     {
102         CL(next,- 1);
103         cnt =  0 ;
104         NN =  2*n  ; // NN 为  加完点 之后的 总结点数
105           for(i =  1;i <=n;i++)
106         {
107             scanf( " %d ",&a);
108             add(i,i+n,a) ;
109         }
110          for(i =  0; i<m;i++)
111         {
112             scanf( " %d%d ",&x,&y);
113             add(x+n,y,INF);
114             add(y + n,x,INF);
115         }
116 
117          int ans = isap(b,t + n) ;
118         printf( " %d\n ",ans) ;
119     }
120 }

 

 

转载于:https://www.cnblogs.com/acSzz/archive/2012/09/21/2697548.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值