• HDU 2435 There is a war Dinic 最小割


    题意是有n座城市,n号城市不想让1号城市可达n号,每条道路有一条毁坏的代价,1号还可以修一条不能毁坏的道路,求n号城市所需的最小代价最大是多少。

    毁坏的最小代价就直接求一遍最大流,就是最小割了。而可以修一条不能毁坏的路,需要枚举的这些边就是源集中的点到汇集中的点,我之前的做法是直接找出所有的割边,再枚举每一条割边,在这两个点上加一个流量为无穷大的边再去求最大流,实际上这样连样例的第二个数据都过不了,因为图不保证是连通的,那就有一些源集中的点和汇集中的点本来就不联通,就不存在这样的割边了。发现这个错误后,我就在没有联通的所有边中加了一条cap为0的边,想弥补上面的bug,但是这样的话超时了。奇怪的是,我没有加那些cap为0的点的时候也是超时而不是wa。

    所以就找出所有的源点,找出所有的汇点,去除1和n后枚举这些边在原来的基础上去跑最大流,得出来的意义就是如果修的是这条路,所需要的额外的代价。

    我自己的代码不知道为什么过不了,可能是模板的问题?

    贴两个代码吧,前面是自己的,后面是别人的。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <fstream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <deque>
      7 #include <vector>
      8 #include <queue>
      9 #include <string>
     10 #include <cstring>
     11 #include <map>
     12 #include <stack>
     13 #include <set>
     14 #define LL long long
     15 #define eps 1e-8
     16 #define INF 0x3f3f3f3f
     17 #define MAXN 105
     18 #define OPEN_FILE
     19 using namespace std;
     20 int S;
     21 struct Edge{
     22     int from, to, cap, flow;
     23     //Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){};
     24 };
     25 vector<Edge> cutset;
     26 bool comp(const Edge& a, const Edge& b){
     27     return (a.from < b.from || (a.from == b.from && a.to < b.to));
     28 }
     29 struct Dinic{
     30     int n, m, i, s, t;
     31     Edge e;
     32     vector<Edge> edges;
     33     vector<int> G[MAXN];
     34     int d[MAXN], cur[MAXN];
     35 //    bool vis[MAXN];
     36     int Q[MAXN * 10];
     37 
     38     void init(int n){
     39         this->n = n;
     40         for (i = 0; i <= n; i++){
     41             G[i].clear();
     42         }
     43         edges.clear();
     44     }
     45     void AddEdge(int from, int to, int cap){
     46         edges.push_back(Edge{ from, to, cap, 0 });
     47         edges.push_back(Edge{ to, from, 0, 0 });
     48         m = edges.size();
     49         G[from].push_back(m - 2);
     50         G[to].push_back(m - 1);
     51     }
     52     bool BFS(){
     53     //    memset(vis, 0, sizeof(vis));
     54         int head = 0, tail = 0;
     55         Q[head] = s;
     56         memset(d, 0, sizeof(d));
     57         d[s] = 1;
     58         S = 0;
     59         while (head <= tail){
     60             int x = Q[head++];
     61             for (i = 0; i < G[x].size(); i++){
     62                 Edge& e = edges[G[x][i]];
     63                 if (d[e.to] == 0 && e.cap > e.flow){
     64                     d[e.to] = d[x] + 1;
     65                     Q[++tail] = e.to;
     66                     S++;
     67                 }
     68             }
     69         }
     70         if (d[t] == 0){
     71             return false;
     72         }
     73         else{
     74             return true;
     75         }
     76     }
     77     int DFS(int x, int a){
     78         if (x == t || a == 0) return a;
     79         int flow = 0, f;
     80         for (int& i = cur[x]; i < G[x].size(); i++){
     81             Edge& e = edges[G[x][i]];
     82             if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0){
     83                 e.flow += f;
     84                 edges[G[x][i] ^ 1].flow -= f;
     85                 flow += f;
     86                 a -= f;
     87                 if (a == 0) break;
     88             }
     89         }
     90         return flow;
     91     }
     92     int MaxFlow(int s, int t, int need){
     93         int flow = 0;
     94         this->s = s;
     95         this->t = t;
     96         while (BFS()){
     97             memset(cur, 0, sizeof(cur));
     98             flow += DFS(s, INF);
     99             if (flow > need) return flow;
    100         }
    101         return flow;
    102     }
    103 };
    104 int n, m;
    105 Dinic p, q;
    106 int RIGHT[MAXN];
    107 int main()
    108 {
    109 #ifdef OPEN_FILE
    110     freopen("in.txt", "r", stdin);
    111     //freopen("out.txt", "w", stdout);
    112 #endif // OPEN_FILE
    113     int T;
    114     scanf("%d", &T);
    115     for (int cas = 1; cas <= T; cas++){
    116         scanf("%d%d", &n, &m);
    117         p.init(n);
    118         int x, y, z;
    119     //    memset(conn, 0, sizeof(conn));
    120         for (int i = 1; i <= m; i++){
    121             scanf("%d%d%d", &x, &y, &z);
    122             p.AddEdge(x, y, z);
    123         //    conn[x][y] = true;
    124             //conn[y][x] = true;
    125         }
    126         //int res = p.MaxFlow(1, n, INF);
    127         //p.AddEdge(2, 3, INF);
    128         //q = p;
    129         int res = p.MaxFlow(1, n, INF);
    130         int cnt = 1;
    131     //    memset(isR, 0, sizeof(isR));
    132         for (int i = 2; i < n; i++){
    133             if (p.d[i] == 0){
    134                 RIGHT[cnt++] = i;
    135             }
    136         }
    137         cnt--;
    138         int ans = 0;
    139         for (int i = 0; i <= S; i++){
    140             if (p.Q[i] == 1 || p.Q[i] == n) continue;
    141             for (int j = 1; j <= cnt; j++){
    142                 q = p;    
    143                 q.AddEdge(p.Q[i], RIGHT[j], INF);
    144                 int o = q.MaxFlow(1, n, INF);
    145                 ans = max(ans, o);
    146             }
    147         }
    148 //         int ans = 0;
    149 //         for (int i = 0; i < cutset.size(); i++){
    150 //             q = p;
    151 //             q.AddEdge(cutset[i].from, cutset[i].to, INF);
    152 //             int o = q.MaxFlow(1, n, INF);
    153 //             ans = max(ans, o);
    154 //         }
    155         printf("%d
    ", ans + res);
    156         //    printf("%d
    ", p.MaxFlow(1, n, INF));
    157     }
    158 }
    View Code
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<set>
      5 #include<cstdio>
      6 #include<string>
      7 #include <algorithm>
      8 using namespace std;
      9 const int maxn = 105;
     10 //const int maxm=300006;
     11 const int inf = 1 << 30;    
     12 
     13 
     14 struct node
     15 {
     16     int v, next;
     17     int val;
     18 };
     19 int topset;
     20 struct dinic{
     21     node s[maxn*maxn * 2];
     22 
     23 
     24     int level[maxn];//顶点的层次
     25     int p[maxn];
     26     int que[maxn * 10];//BFS中用于遍历的顶点,DFS求增广中记录边
     27     int out[10 * maxn];//DFS用于几乎定点的分支
     28     int ind;
     29 
     30 
     31     int cop_poit[maxn];
     32     node cop_mp[maxn*maxn * 2];
     33 
     34 
     35 
     36     void init()
     37     {
     38         ind = 0;
     39         memset(p, -1, sizeof(p));
     40     }
     41 
     42 
     43     inline void insert(int x, int y, int z)
     44     {
     45         s[ind].v = y;
     46         s[ind].val = z;
     47         s[ind].next = p[x];
     48         p[x] = ind++;
     49         s[ind].v = x;
     50         s[ind].val = 0;
     51         s[ind].next = p[y];
     52         p[y] = ind++;
     53     }
     54 
     55 
     56     int max_flow(int n, int source, int sink)
     57     {
     58         int ret = 0;
     59         int h = 0, r = 0;
     60         while (1)//DFS
     61         {
     62             int i;
     63             for (i = 0; i <= n; ++i)
     64                 level[i] = 0;
     65             h = 0, r = 0;
     66             level[source] = 1;
     67             que[0] = source;
     68             while (h <= r)//BFS
     69             {
     70                 int  t = que[h++];
     71                 for (i = p[t]; i != -1; i = s[i].next)
     72                 {
     73                     if (s[i].val&&level[s[i].v] == 0)
     74                     {
     75                         level[s[i].v] = level[t] + 1;
     76                         que[++r] = s[i].v;
     77                     }
     78                 }
     79             }
     80             topset = r;//记录原点的集合个数
     81 
     82 
     83             if (level[sink] == 0)break;//找不到汇点
     84             for (i = 0; i <= n; ++i)
     85                 out[i] = p[i];
     86 
     87 
     88             int  q = -1;
     89             while (1)
     90             {
     91                 if (q < 0)
     92                 {
     93                     int  cur = out[source];
     94                     for (; cur != -1; cur = s[cur].next)
     95                     {
     96                         if (s[cur].val&&out[s[cur].v] != -1 && level[s[cur].v] == 2)
     97                         {
     98                             break;
     99                         }
    100                     }
    101                     if (cur >= 0)
    102                     {
    103                         que[++q] = cur;
    104                         out[source] = s[cur].next;
    105                     }
    106                     else
    107                     {
    108                         break;
    109                     }
    110                 }
    111 
    112 
    113                 int  u = s[que[q]].v;
    114 
    115 
    116                 if (u == sink)//一条增广路
    117                 {
    118                     int  dd = inf;
    119                     int  index = -1;
    120                     for (i = 0; i <= q; i++)
    121                     {
    122                         if (dd > s[que[i]].val)
    123                         {
    124                             dd = s[que[i]].val;
    125                             index = i;
    126                         }
    127                     }
    128                     ret += dd;
    129                     //cout<<ret<<endl;
    130                     for (i = 0; i <= q; i++)
    131                     {
    132                         s[que[i]].val -= dd;
    133                         s[que[i] ^ 1].val += dd;
    134                     }
    135                     for (i = 0; i <= q; i++)
    136                     {
    137                         if (s[que[i]].val == 0)
    138                         {
    139                             q = index - 1;
    140                             break;
    141                         }
    142                     }
    143                 }
    144                 else
    145                 {
    146                     long cur = out[u];
    147                     for (; cur != -1; cur = s[cur].next)
    148                     {
    149                         if (s[cur].val&&out[s[cur].v] != -1 && level[u] + 1 == level[s[cur].v])
    150                         {
    151                             break;
    152                         }
    153                     }
    154                     if (cur != -1)
    155                     {
    156                         que[++q] = cur;
    157                         out[u] = s[cur].next;
    158                     }
    159                     else
    160                     {
    161                         out[u] = -1;
    162                         q--;
    163                     }
    164                 }
    165             }
    166         }
    167         return ret;
    168     }
    169 };
    170 
    171 int m, n;
    172 int q[maxn * 10];
    173 dinic x, y;
    174 int main()
    175 {
    176     freopen("in.txt", "r", stdin);
    177     int cas;
    178     cin >> cas;
    179     int huijie[maxn];
    180     while (cas--)
    181     {
    182         x.init();
    183         scanf("%d%d", &n, &m);
    184         for (int i = 0; i < m; i++)
    185         {
    186             long from, to, cost;
    187             scanf("%d %d %d", &from, &to, &cost);
    188             x.insert(from, to, cost);
    189         }
    190         long Start, End;
    191         Start = 1; End = n;
    192         int tmp = x.max_flow(n, Start, End);//计算一次最大流(最小割)
    193 
    194 
    195         y = x;
    196 
    197         int ans = 0;
    198         int r = 0;
    199 
    200 
    201         for (int j = 2; j < n; j++)//求出汇集---因为bfs找不到一条增广路时,qu中就是原集,剩下来就是汇集,也可以是leve数组便利不到的顶点
    202         {
    203             if (x.level[j] == 0)
    204                 huijie[r++] = j;
    205         }
    206 
    207         for (int i = 0; i <= topset; i++)//枚举两顶点
    208         {
    209             if (x.que[i] == 1 || x.que[i] == n) continue;
    210             for (int j = 0; j < r; j++)
    211             {
    212                 y = x;
    213                 y.insert(x.que[i], huijie[j], inf);//加边
    214                 int g = y.max_flow(n, 1, n);//格外的代价
    215                 ans = max(ans, g);
    216             }
    217         }
    218         printf("%d
    ", ans + tmp);
    219     }
    220     return 0;
    221 }
    View Code
  • 相关阅读:
    Nginx配置文件的路径
    有关Tomcat 8.5版本文件上传后无权限访问的问题
    常见HTTP状态码列表
    服务器BMC(带外)
    CDN问题
    PECE
    linux系统概述
    干货--整蛊你的舍友
    arp请求与回复
    huawei oceanstor
  • 原文地址:https://www.cnblogs.com/macinchang/p/4694237.html
Copyright © 2020-2023  润新知