zoukankan      html  css  js  c++  java
  • HDU 3987 Harry Potter and the Forbidden Forest

    题意:给出一张有n个点的图,有的边又向,有的边无向,现在要你破坏一些路,使得从点0无法到达点n-1。破坏每条路都有一个代价。求在代价最小的前提下,最少需要破坏多少条道路。(就是说求在最小割的前提下,最小的割边数)

    这题做了长姿势了。偏移量的方法没有想到。如果采用偏移量的方法的话,把每条边的边权w设为w'=w*MOD+1,然后求最小割,那么maxflow%MOD就是答案了。前提是MOD足够大。

    另外一种方法,利用一个结论:最小割边一定满流,满流的未必是最小割边。假设所有满流的边都是最小割边,把它们的cap全部设为1,其余未满流的边的cap设为inf,然后求最小割,答案就是最小割值。虽然没搞懂怎么证明这个做法是对的,也觉得这个做法有点邪乎,但它就是对的。也就是说,最小割不唯一的情况下,未出现在一个最小割中却出现在另外一个最小割中的边一定也是满流的(真不知道到底对不对)。

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define INF 1<<30
     6 #define maxn 1010
     7 #define maxm 500000
     8 using namespace std;
     9 
    10 int v[maxm],next[maxm],w[maxm];
    11 int first[maxn],d[maxn],work[maxn],q[maxn];
    12 int e,S,T;
    13 
    14 void init(){
    15     e = 0;
    16     memset(first,-1,sizeof(first));
    17 }
    18 
    19 void add_edge(int a,int b,int c){
    20     v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
    21     v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
    22 }
    23 
    24 int bfs(){
    25     int rear = 0;
    26     memset(d,-1,sizeof(d));
    27     d[S] = 0;q[rear++] = S;
    28     for(int i = 0;i < rear;i++){
    29         for(int j = first[q[i]];j != -1;j = next[j])
    30             if(w[j] && d[v[j]] == -1){
    31                 d[v[j]] = d[q[i]] + 1;
    32                 q[rear++] = v[j];
    33                 if(v[j] == T)   return 1;
    34             }
    35     }
    36     return 0;
    37 }
    38 
    39 int dfs(int cur,int a){
    40     if(cur == T)    return a;
    41     for(int &i = work[cur];i != -1;i = next[i]){
    42         if(w[i] && d[v[i]] == d[cur] + 1)
    43             if(int t = dfs(v[i],min(a,w[i]))){
    44                 w[i] -= t;w[i^1] += t;
    45                 return t;
    46             }
    47     }
    48     return 0;
    49 }
    50 
    51 int dinic(){
    52     int ans = 0;
    53     while(bfs()){
    54         memcpy(work,first,sizeof(first));
    55         while(int t = dfs(S,INF))   ans += t;
    56     }
    57     return ans;
    58 }
    59 
    60 int main()
    61 {
    62     int n,m,nkase;
    63     scanf("%d",&nkase);
    64     for(int kase = 1;kase <= nkase;kase++){
    65         init();
    66         scanf("%d%d",&n,&m);
    67         S = 0,T = n-1;
    68         for(int i = 0;i < m;i++){
    69             int a,b,c,d;
    70             scanf("%d%d%d%d",&a,&b,&c,&d);
    71             add_edge(a,b,c);
    72             if(d == 1)  add_edge(b,a,c);
    73         }
    74         dinic();
    75         for(int i = 0;i < e;i += 2){
    76             if(w[i] == 0){
    77                 w[i] = 1;
    78                 w[i^1] = 0;
    79             }else{
    80                 w[i] = INF;
    81                 w[i^1] = 0;
    82             }
    83         }
    84         printf("Case %d: %d
    ",kase,dinic());
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    java设计模式-适配器模式
    java设计模式-外观模式
    java设计模式-享元模式
    java设计模式-装饰模式
    java设计模式-组合模式
    java设计模式-桥接模式
    12月Java原生商城APP源码-完全开源
    uniapp插件市场-涂图视频编辑-美妆-剪辑-微整形原生sdk插件发布-优雅草科技
    12月最新仿知音漫画网站源码+手机端,小说漫画生成静态文件,超强负载量安全可靠
    如何把网易云音乐ncm格式转换成mp3格式---记一下
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3400230.html
Copyright © 2011-2022 走看看