[最小割最大流 || 最短路] roadblock Dinic && SPFA + SLE

时间:2021-09-03 04:25:34

大家都很强, 可与之共勉。

震惊!cky 竟率兵攻打jyb!
jyb 面对强敌,振作精神,想要抗击侵略。jyb 的国家一共有n 个城市,m 条距离为1 的双向道路。现在jyb的所在地是1 号城市,cky 已经占领了n 号城市。jyb 得到线报,cky 想要走最近的路线抓到自己,而jyb 还在调集部队,所以他希望拖延一点时间。他派出了一些工程人员去破坏道路,破坏每条道路都要消耗一定的资源,jyb 希望消耗最小的资源并且保证能拖延到cky。

Input
第1 行,1 个整数T, 表示数据组数,对于每组数据:
第1 行,2 个整数n;m,表示城市数和道路数
接下来m 行,每行3 个整数u; v;w, 表示城市u 到城市v 有一条路,破坏消耗的资源为w。
Output
对于每组数据,输出最小消耗的资源。
Sample
roadblock.in
1
4 4
1 2 1
2 4 2
3 1 3
4 3 4
roadblock.out
4

数据范围:
1 T 5, 1 n 1000,1 m 10000,1 w 300000。

题意其实挺简单的,先BFS找出最短路,因为边权为1,最短路显然有很多,然后我们建一个只有最短路上边的新图,然后跑出最小割就好。需要加当前弧优化才能过所有点。

调了我好久啊, 天哪!

#include "queue"
#include "cctype"
#include "cstdio"
#include "cstring"

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define rep(i, m, n) for(register int i = (m); i <= (n); ++i)
#define edges(u) for(register int i = head[u]; i; i = g[i].pre)

template <class T>
inline bool readIn(T &x)  {
    T opt = 1;
    static char ch;
    while(!isdigit(ch = (char) getchar()) && (ch ^ -1) && (ch ^ 45));
    if(ch == -1)  return false;
    if(ch == 45)  opt = -1, ungetc(ch, stdin);
    for(x = -48 + ch; isdigit(ch = (char) getchar()); x = (x << 1) + (x << 3) + ch - 48);
    x *= opt;
    return true;
}

template <class T>
inline bool writeIn(T x)  {
    T st[25], top = 0;
    if(x < 0)  putchar('-'), x = -x;
    if(x == 0)  {  putchar(48); return true;  }
    while(x)  st[++top] = x % 10, x /= 10;
    while(top)  putchar(st[top--] + 48);
    return true;
}

const int oo = 0x3f3f3f3f;

struct edge  {
    int to, pre, cost;
    edge(int to = 0, int pre = 0, int cost = 0) : to(to), pre(pre), cost(cost) {  }
} g[20005];

struct Edge  {
    int to, cap, flow, pre;
    Edge(int to = 0, int flow = 0, int cap = 0, int pre = 0) : to(to), flow(flow), cap(cap), pre(pre) {  }
} e[20005];

typedef long long LL;

int T, n, m, tot, ne, head[10005], dis1[10005], dis2[10005], u[10005], v[10005], w[10005];
LL ans;

void SPFA(int s, int t)  {
    static std::deque<int> q;
    static bool vis[10005];
    memset(dis1, 0x3f, sizeof (int) * (n + 1));
    memset(dis2, 0x3f, sizeof (int) * (n + 1));
    memset(vis, false, sizeof (int) * (n + 1));
    q.push_front(s); vis[s] = true; dis1[s] = 0;
    while( !q.empty() )  {
        int u = q.front(); q.pop_front();
        vis[u] = false;
        edges(u)  {
            int v = g[i].to;
            if( dis1[v] > dis1[u] + 1 )  {
                dis1[v] = dis1[u] + 1;
                if( !vis[v] )  {
                    if( q.empty() || dis1[v] < dis1[q.front()] )
                        q.push_front(v);
                    else
                        q.push_back(v);
                    vis[v] = true;
                }
            }
        }
    }
    memset(vis, false, sizeof (int) * (n + 1));
    q.push_front(t); vis[t] = true; dis2[t] = 0;
    while( !q.empty() )  {
        int u = q.front(); q.pop_front();
        vis[u] = false;
        edges(u)  {
            int v = g[i].to;
            if( dis2[v] > dis2[u] + 1 )  {
                dis2[v] = dis2[u] + 1;
                if( !vis[v] )  {
                    if( q.empty() || dis2[v] < dis2[q.front()] )
                        q.push_front(v);
                    else
                        q.push_back(v);
                    vis[v] = true;
                }
            }
        }
    }
}

class Dinic  {
public:
    int d[10005], cur[10005], s, t;
    std::queue<int> Q;
    bool vis[10005];
     bool bfs(int s, int t)  {       
        memset(vis, false, sizeof (int) * (n + 1));
        d[s] = 0, vis[s] = true;
        Q.push(s);
        while(!Q.empty())  {
            int u = Q.front();  Q.pop();
            for( int i = head[u]; i; i = e[i].pre )  {
                int v = e[i].to;
                if( !vis[v] && e[i].cap > e[i].flow )  {
                    vis[v] = true;
                    d[v] = d[u] + 1;
                    Q.push(v);
                }
            }
        }
        return vis[t];
    }

    int dfs( int u, int a )  {
        if( u == t || !a )  return a;
        int flow = 0, f;
        for(register int &i = cur[u]; i; i = e[i].pre )  {
            int  v = e[i].to;
            if( d[u] + 1 == d[v] && (f = dfs(v, min(e[i].cap - e[i].flow, a))) > 0)  {
                e[i].flow += f;
                e[i^1].flow -= f;
                flow += f;
                a -= f;
                if(!a)  return flow;
            }
        }
        return flow;
    }

    int Maxflow( int s, int t )  {
        this->s = s, this->t = t;
        int flow = 0;
        while( bfs( s, t ) )  {
            rep(i, 1, n)  cur[i] = head[i];
            flow += dfs( s, oo );
        }
        return flow;
    }
} M;

#define adde(u, v, cost) { g[++ne] = edge(v, head[u], cost); head[u] = ne; }

inline void initialize()  {
    readIn(n);readIn(m); ne = 1, tot = 0;
    memset(head, 0, sizeof (int) * (n + 1));
    int x, y, o;
    while( m-- )  {
        readIn(x);readIn(y);readIn(o);
        adde(x, y, o);adde(y, x, o);
    }
    SPFA(1, n);
    rep(x, 1, n)  edges(x)  if(dis1[x] + dis2[g[i].to] + 1 == dis1[n])  { u[++tot] = x, v[tot] = g[i].to, w[tot] = g[i].cost; }
    ne = 1;
    memset(head, 0, sizeof (int) * (n + 1));
    rep(i, 1, tot)  {
        e[++ne] = Edge(v[i], 0, w[i], head[u[i]]); head[u[i]] = ne;  
        e[++ne] = Edge(u[i], 0, 0, head[v[i]]); head[v[i]] = ne;
    }
}

int main()  {
    freopen("roadblock.in", "r", stdin);
    freopen("roadblock.out", "w", stdout);
    for(readIn(T); T; --T)  {
        initialize();
        writeIn(M.Maxflow(1, n));
        putchar(10);
    }
}