hdu3549(网络流最大流入门)

Flow Problem
Time Limit: 5000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 20026 Accepted Submission(s): 9425

Problem Description
Network flow is a well-known difficult problem for ACMers. Given a graph, your task is to find out the maximum flow for the weighted directed graph.

Input
The first line of input contains an integer T, denoting the number of test cases.
For each test case, the first line contains two integers N and M, denoting the number of vertexes and edges in the graph. (2 <= N <= 15, 0 <= M <= 1000)
Next M lines, each line contains three integers X, Y and C, there is an edge from X to Y and the capacity of it is C. (1 <= X, Y <= N, 1 <= C <= 1000)

Output
For each test cases, you should output the maximum flow from source 1 to sink N.

Sample Input
2
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1

Sample Output
Case 1: 1
Case 2: 2

Author
HyperHexagon

Source

网络流推荐博客:https://blog.csdn.net/txl199106/article/details/64441994
简单的EK算法是会超时的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int MAXN = 430;
const int MAX_INT = 0x3f3f3f3f;

struct Edge{
    int v,nxt,w;
};

struct Node{
    int v,id;
};

int n,m,ecnt;
bool vis[MAXN];
int head[MAXN];
Node pre[MAXN];
Edge edge[MAXN];

void init()
{
    ecnt = 0;
    memset(edge,0,sizeof(edge));
    memset(head,-1,sizeof(head));
}

void addEdge(int u,int v,int w)
{
    edge[ecnt].v = v;
    edge[ecnt].w = w;
    edge[ecnt].nxt = head[u];
    head[u] = ecnt++;
}

bool bfs(int s,int t)
{
   queue<int>que;
   memset(vis,0,sizeof(vis));
   memset(pre,-1,sizeof(pre));
   pre[s].v = s;
   vis[s] = true;
   que.push(s);
   while(!que.empty())
   {
       int u = que.front();
       que.pop();
       for(int i = head[u];i + 1;i = edge[i].nxt){
            int v = edge[i].v;
            if(!vis[v] && edge[i].w){
                pre[v].v = u;
                pre[v].id = i;
                vis[v] = true;
                if(v == t) return true;
                que.push(v);
            }
       }
   }
   return false;
}

int EK(int s,int t)
{
    int ans = 0;
    while(bfs(s,t))
    {
        int mi = MAX_INT;
        for(int i = t;i != s;i = pre[i].v)
        {
            mi = min(mi,edge[pre[i].id].w);
        }
        for(int i = t;i != s;i = pre[i].v)
        {
            edge[pre[i].id].w -= mi;
            edge[pre[i].id ^ 1].w += mi;
        }
        ans += mi;
    }
    return ans;
}

int main()
{
    int t;
    scanf("%d",&t);
    int k = 1;
    while(t--)
    {
        init();
        scanf("%d %d",&n,&m);
        for(int i = 0;i < m;++i)
        {
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
            addEdge(u,v,w);
            addEdge(v,u,0);
        }
        printf("Case %d: ",k++);
        int ans = EK(1,n);
        printf("%d\n",ans);
    }
    return 0;
}

Dinic算法是可以过的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int MAXN = 1050;
const int MAX_INT = 0x3f3f3f3f;

int n,m;
int dis[MAXN];
int mp[MAXN][MAXN];

void init()
{
    memset(mp,0,sizeof(mp));
}

int bfs(int s)
{
    memset(dis,-1,sizeof(dis));
    dis[s] = 0;
    queue<int>que;
    que.push(s);
    while(!que.empty())
    {
        int top= que.front();
        que.pop();
        for(int i = 1;i <= n;++i)
        {
            if(dis[i] < 0 && mp[top][i] > 0)
            {
                dis[i] = dis[top] + 1;
                que.push(i);
            }
        }
    }
    if(dis[n] > 0) return true;
    return false;
}

int Find(int x,int low)
{
    int a = 0;
    if(x == n) return low;
    for(int i = 1;i <= n;++i)
    {
        if(mp[x][i] > 0 && dis[i] == dis[x] + 1 && (a = Find(i,min(mp[x][i],low)))){
            //这儿深搜到底部才会返回
            mp[x][i] -= a;
            mp[i][x] += a;
            return a;
        }
    }
    return 0;
}

int main()
{
    int t;
    scanf("%d",&t);
    int k = 1;
    while(t--)
    {
        scanf("%d %d",&n,&m);
                init();
        for(int i = 0;i < m;++i)
        {
            int u,v,w;
            scanf("%d %d %d",&u,&v,&w);
                mp[u][v] += w;
        }
        int ans = 0,tmp;
        printf("Case %d: ",k++);
        while(bfs(1)){
            while(tmp = Find(1,MAX_INT))
                ans += tmp;
        }
        printf("%d\n",ans);
    }
    return 0;
}

Dinic(弧优化和多路增广):

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1005;
const int MAXN_INT = (1 << 29);

struct Edge{
    int v, w, nxt;
};

int s, t;
int n, m, ecnt;
Edge edge[MAXN * 2];
int head[MAXN], dis[MAXN], curEdge[MAXN];

void init(){
    ecnt = 0;
    s = 1;
    t = n;
    memset(edge, 0, sizeof(edge));
    memset(head, -1, sizeof(head));
}

void addEdge(int u, int v, int w){
    edge[ecnt].v = v;
    edge[ecnt].w = w;
    edge[ecnt].nxt = head[u];
    head[u] = ecnt++;
}

int bfs(){
    memset(dis,-1,sizeof(dis));
    dis[t] = 0;
    queue <int> que;
    que.push(t);
    while(!que.empty()){
        int u = que.front();
        que.pop();
        for(int i = head[u]; i + 1; i = edge[i].nxt){
            if(dis[edge[i].v] == -1 && edge[i ^ 1].w > 0){
                dis[edge[i].v] = dis[u] + 1;
                que.push(edge[i].v);
            }
        }
    }
    return dis[s] != -1;
}

int dfs(int u, int v, int flow){
    if(u == t) return flow;
    int delta = flow;
    for(int &i = curEdge[u]; i + 1; i = edge[i].nxt){
        if(dis[u] == dis[edge[i].v] + 1 && edge[i].w){
            int d = dfs(edge[i].v, v, min(delta, edge[i].w));
            edge[i].w -= d, edge[i ^ 1].w += d;
            delta -= d;
            if(delta == 0) break;
        }
    }
    return flow - delta;
}

int dinic(){
    int ans = 0;
    while(bfs()){
        for(int i = 0; i < n; i++)
            curEdge[i] = head[i];
        ans += dfs(s, t, MAXN_INT);
    }
    return ans;
}

int main(){
    int t;
    scanf("%d",&t);
    int k = 1;
    while(t--){
        scanf("%d %d", &n, &m);
        init();
        int u, v, w;
        for(int i = 0; i < m; i++){
            scanf("%d%d%d", &u, &v, &w);
            addEdge(u, v, w);
            addEdge(v, u, 0);
        }
        printf("Case %d: %d\n",k++,dinic());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36386435/article/details/80197361