HDU6214 Smallest Minimum Cut (最大流SAP)

题目链接:点击打开链接

文章转载自:xuanqis.com

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;  
}  

全部评论

相关推荐

牛客101244697号:这个衣服和发型不去投偶像练习生?
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务