Harry Potter and the Forbidden Forest HDU - 3987 (minimum cut)

Posted by blacksmoke26 on Wed, 23 Oct 2019 17:20:55 +0200

Title Link: https://cn.vjudge.net/problem/HDU-3987

Here are n points and m edges (both unidirectional and bidirectional). Since there are more than one minimum cut, find the cut set with the least number of edges and output the least number of edges.

Two ideas:

1. Run the maximum flow first, then set the capacity of the saturated side to 1, the unsaturated side to INF, and then run the maximum flow again.

2. Multiply the edge weight of each side by a number greater than the number of sides plus 1, then run the side of the maximum flow, and finally output the number% multiplied by the result.

#include <algorithm>
#include <vector>
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX = (1ll << 31) - 1;
const int mavn = 4e5+5;
const int maxn = 1e5+5;
#define ll long long
struct Edge{
    int to;
    ll dis;
    int rev;
    Edge(){}
    Edge(int to,ll d,int c):to(to),dis(d),rev(c){}
};
vector<Edge> v[maxn];
int cur[mavn];
int n, m, s, t;
struct node {
	int u,v,d;
	ll c;
	node(){}
	node(int a,int b,ll c,int d):u(a),v(b),c(c),d(d){}
}pos[mavn];
void addEdge(int from, int to, ll dis){
    v[from].push_back(Edge(to, dis,v[to].size()));
    v[to].push_back(Edge(from, 0,v[from].size()-1));
}
int d[mavn],cnt;
ll DFS(int u, ll flow){
    if (u == t || !flow) return flow;
    ll ans = 0, tmp_flow;
    for (int& i = cur[u]; i < v[u].size(); i++){
        int to = v[u][i].to;
        if (d[to] == d[u] + 1 && v[u][i].dis > 0){
            tmp_flow = DFS(to, min(flow, v[u][i].dis));
            if(tmp_flow > 0) {
        	flow -= tmp_flow;
		v[u][i].dis -= tmp_flow;
		ans += tmp_flow;
		v[to][v[u][i].rev].dis += tmp_flow;
		if (!flow)
	            break;
            }
        }
    }
    if (!ans) d[u] = -1;
    return ans;
}
bool BFS(){
    memset(d,-1,sizeof(d));
    queue<int> que;
    que.push(s);
    d[s] = 0;
    int u, _new;
    while (!que.empty()){
        u = que.front();
        que.pop();
        for (int i = 0; i < v[u].size(); i++){
            _new = v[u][i].to;
            if (d[_new] == -1 && v[u][i].dis > 0){
                d[_new] = d[u] + 1;
                que.push(_new);
            }
        }
    }
    return (d[t] != -1);
}
ll  dinic(){
    ll max_flow = 0;
    cnt=0;
    while (BFS()){
        memset(cur,0,sizeof(cur));
        ll t;
        while((t = DFS(s,MAX)) > 0) max_flow += t;
    }
	return max_flow;
}

int T,case=1;

int main(){
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) {
            int x,y,a;	ll c;
            scanf("%d%d%lld%d",&x,&y,&c,&a);
            addEdge(x,y,c*(m+1) + 1);
            if(a) addEdge(y,x,c*(m+1)+1);
        }
        s = 0, t = n - 1;
        ll maxx = dinic();
        printf("Case %d: %lld\n",case++,maxx % (m+1));
        for(int i=0;i<=n;i++) v[i].clear();
    }

	return 0;
}