HDU6214 Smallest Minimum Cut (最大流SAP)

题目链接:点击打开链接

 

description

Consider a network G=(V,E) with source s and sink t. An s-t cut is a partition of nodes set V into two parts such that s and t belong to different parts. The cut set is the subset of E with all edges connecting nodes in different parts. A minimum cut is the one whose cut set has the minimum summation of capacities. The size of a cut is the number of edges in the cut set. Please calculate the smallest size of all minimum cuts.

Input

The input contains several test cases and the first line is the total number of cases T (1≤T≤300).
Each case describes a network G, and the first line contains two integers n (2≤n≤200) and m (0≤m≤1000) indicating the sizes of nodes and edges. All nodes in the network are labelled from 1 to n.
The second line contains two different integers s and t (1≤s,t≤n) corresponding to the source and sink.
Each of the next m lines contains three integers u,v and w (1≤w≤255) describing a directed edge from node u to v with capacity w.

Output

For each test case, output the smallest size of all minimum cuts in a line.

Sample Input

2
4 5
1 4
1 2 3
1 3 1
2 3 1
2 4 1
3 4 2
4 5
1 4
1 2 3
1 3 1
2 3 1
2 4 1
3 4 3

Sample Output

2
3

题意

输入t组数据,每组数据第一行是图的点数n和边数m,第二行是计算的最大流的起点start和终点end,接下来的m行是边的两个临接点和边的权值。求最小割的最少边数。

思路

将每一条边都乘以一个MOD再加1,求出的最大流求余MOD的值就是最小割的边的数量。

代码

时间:218ms

#include <stdio.h>  
#include <string.h>  
#include <iostream>  
#include <algorithm>  
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <string>  
#include <math.h>  
#include <stdlib.h>  
#include <time.h>  
using namespace std;  

const int MAXN = 1010;//点数的最大值  
const int MAXM = 400010;//边数的最大值  
const int INF = 0x3f3f3f3f;  
struct Edge{  
    int to,next,cap,flow;  
}edge[MAXM];//注意是MAXM  
int tol;  
int head[MAXN];  
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];  
void init(){  
    tol = 0;  
    memset(head,-1,sizeof(head));  
}  
//加边,单向图三个参数,双向图四个参数  
void addedge(int u,int v,int w,int rw=0){  
    edge[tol].to = v;edge[tol].cap = w;edge[tol].next = head[u];  
    edge[tol].flow = 0;head[u] = tol++;  
    edge[tol].to = u;edge[tol].cap = rw;edge[tol].next = head[v];  
    edge[tol].flow = 0;head[v]=tol++;  
}  
int sap(int start,int end,int N){  //kuangbin的SAP模板 
    memset(gap,0,sizeof(gap));  
    memset(dep,0,sizeof(dep));  
    memcpy(cur,head,sizeof(head));  
    int u = start;  
    pre[u] = -1;  
    gap[0] = N;  
    int ans = 0;  
    while(dep[start] < N){  
        if(u == end){  
            int Min = INF;  
            for(int i = pre[u];i != -1; i = pre[edge[i^1].to])  
                if(Min > edge[i].cap - edge[i].flow)  
                        Min = edge[i].cap - edge[i].flow;  
            for(int i = pre[u];i != -1; i = pre[edge[i^1].to]){  
                edge[i].flow += Min;  
                edge[i^1].flow -= Min;  
            }  
            u = start;  
            ans += Min;  
            continue;  
        }  
        bool flag = false;  
        int v;  
        for(int i = cur[u]; i != -1;i = edge[i].next){  
            v = edge[i].to;  
            if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u]){  
                flag = true;  
                cur[u] = pre[v] = i;  
                break;  
            }  
        }  
        if(flag){  
            u = v;  
            continue;  
        }  
        int Min = N;  
        for(int i = head[u]; i != -1;i = edge[i].next)  
            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min){  
                Min = dep[edge[i].to];  
                cur[u] = i;  
            }  
        gap[dep[u]]--;  
        if(!gap[dep[u]])return ans;  
        dep[u] = Min+1;  
        gap[dep[u]]++;  
        if(u != start) u = edge[pre[u]^1].to;  
    }  
    return ans;  
}  
int main()  
{  
    //freopen("2.txt", "r", stdin);  
    int m, n;  
    int t;  
    scanf("%d",&t);   //数据组数 
    while(t--)  
    {  
        init();
        scanf("%d%d",&n,&m); //输入点数边数 
        int numa, numb;  //起点终点 
        scanf("%d %d", &numa,&numb);  
        for(int i=1;i<=m;i++)  
        {  
            int u,v,cap;  
            scanf("%d%d%d",&u,&v,&cap);  
            cap=cap*1001+1;  //这里我用的是1001 
            addedge(u,v,cap);  
        }  
            printf("%d\n",sap(numa,numb,n)%1001);  
    }  
    return 0;  
}

另一个ISAP+BFS初始化+栈优化:时间249ms

#include <stdio.h>  
#include <string.h>  
#include <iostream>  
#include <algorithm>  
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <string>  
#include <math.h>  
#include <stdlib.h>  
#include <time.h>  
using namespace std;  

const int MAXN=10001;  
const int MAXM=40001;  
const int INF=0x3f3f3f3f;  
struct Edge{
    int to,next,cap,flow;  
}edge[MAXM];

int tol;  
int head[MAXN];  
int gap[MAXN], dep[MAXN], cur[MAXN];  
void init(){
    tol=0;  
    memset(head,-1,sizeof(head));  
} 

void addedge(int u, int v, int w, int rw=0){
    edge[tol].to=v; edge[tol].cap=w; edge[tol].flow=0;  
    edge[tol].next=head[u]; head[u]=tol++;  
    edge[tol].to=u; edge[tol].cap=rw; edge[tol].flow=0;  
    edge[tol].next=head[v]; head[v]=tol++;  
}

int Q[MAXN];  

void BFS(int start, int end){
    memset(dep,-1,sizeof(dep));  
    memset(gap,0,sizeof(gap));  
    gap[0]=1;  
    int front=0,rear=0;  
    dep[end]=0;  
    Q[rear++]=end;  
    while(front != rear){
        int u = Q[front++];  
        for(int i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].to;  
            if(dep[v]!=-1)continue;  
            Q[rear++]=v;  
            dep[v]=dep[u]+1;  
            gap[dep[v]]++;  
        }
    }
}

int S[MAXN];  
int sap(int start, int end, int N){
    BFS(start,end);  
    memcpy(cur,head,sizeof(head));  
    int top=0;  
    int u=start;  
    int ans=0;  
    while(dep[start]<N){
        if(u==end){
            int Min=INF;  
            int inser;  
            for(int i=0;i<top;i++)
                if(Min > edge[S[i]].cap-edge[S[i]].flow){
                    Min=edge[S[i]].cap-edge[S[i]].flow;  
                    inser=i;  
                }
            for(int i=0;i<top;i++){
                edge[S[i]].flow+=Min;  
                edge[S[i]^1].flow-=Min;  //不懂标记 
            }
            ans +=Min;  
            top=inser;  
            u=edge[S[top]^1].to;  
            continue;  
        }
        bool flag=false;  
        int v;  
        for(int i=cur[u]; i!=-1; i=edge[i].next){
            v=edge[i].to;  
            if(edge[i].cap-edge[i].flow && dep[v]+1 == dep[u]){
                flag=true;  
                cur[u]=i;  
                break;  
            }
        }
        if(flag){
            S[top++]=cur[u];  
            u=v;  
            continue;  
        }
        int Min=N;  
        for(int i=head[u]; i!=-1; i=edge[i].next){
            if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min){
                Min=dep[edge[i].to];  
                cur[u]=i;  
            }
        }
        gap[dep[u]]--;  
        if(!gap[dep[u]])return ans;  
        dep[u]=Min+1;  
        gap[dep[u]]++;  
        if(u != start)u=edge[S[--top]^1].to;  
    }
    return ans;  
}
int main()  
{  
    //freopen("2.txt", "r", stdin);  
    int m, n;  
    int t;  
    scanf("%d",&t);   //数据组数 
    while(t--)  
    {  
        init();
        scanf("%d%d",&n,&m); //输入点数边数 
        int numa, numb;  //起点终点 
        scanf("%d %d", &numa,&numb);  
        for(int i=1;i<=m;i++)  
        {  
            int u,v,cap;  
            scanf("%d%d%d",&u,&v,&cap);  
            cap=cap*1001+1;  //这里我用的是1001 
            addedge(u,v,cap);  
        }  
            printf("%d\n",sap(numa,numb,n)%1001);  
    }  
    return 0;  
}  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值