Los grass drainage Valley P2740 maximum flow entry title

Los grass drainage Valley P2740 maximum flow entry title

The meaning of problems

On Farmer John's farm, whenever it rains, Bessie's favorite clover to build up a body of water. This means that the grass is under water, and the grass will continue to grow it will take quite a long time. Therefore, the farmer John built a drainage system for the turf Bessie exemption was flooded with water troubles (do not worry, the rain will flow to a nearby stream). As a first-class technicians, Farmer John has been the placement of a controller at one end of each gutter, so that he can control the flow of water flowing into drains.

Farmer John know the exact layout of the water, and drainage systems of each gutter can flow per minute (starting point for the pool and the end point of a creek net). Note that, in some cases from one place to another is not only a drain.

Based on this information, calculate the drain from the pool to the maximum flow rate of the stream. For each given drains, rainwater can flow only in one direction, the annular flow of rainwater note case may occur.

Input Format

Line 1: two spaces separated by an integer N (0 <= N <= 200) and M (2 <= M <= 200). N is the number of drains have been dug John Farmer, M is the number of intersections of the gutter. 1 is a pool intersection, the intersection point M is the stream.

The second row to row 1 + N: an integer of three in each row, Si, Ei, and Ci. Si and Ei (1 <= Si, Ei <= M) specified intersection across the drains, rainwater flows from Si Ei. Ci (0 <= Ci <= 10,000,000) is the maximum capacity of this gutter.

Output Format

Output an integer, i.e. maximum flow drainage.

//下面是样例输入
5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10
//样例输出
50

Problem-solving ideas

This is when I learned maximum flow algorithm, see blog entry saying this is a problem, really basic.

Specific maximum flow explain not say, it is recommended to look at this blog network flow algorithm for maximum flow Primer (augmenting path algorithm to the Ford-Fulkerson Edmonds-Karp to dinic) package to read , speak really good, especially his It is the kind of code to achieve the most basic form.

The following code in two versions, one based on his made changes, and the other is to look at the "algorithm contest entry classic (Second Edition)" 368implementation code page, the more advanced it.

Code

//我的EK写法。。。建议邻接矩阵 
//题目:洛谷p2740 草地排水 
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f; 
int m,n,cap[205][205],pre[205],flow[205][205];
int vis[205];
bool bfs(int s,int t)
{
//    memset(pre,-1,sizeof(pre));
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(s);
    vis[s]=inf;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=1;i<=n;i++)
        {
            //这里vis不仅代表标记,还记录了到这个结点可以减去的最小流量值
            //这样就省去了max_flow中的第一个for循环
            if(vis[i]==0 && i!=now && cap[now][i]-flow[now][i]>0)
            {
                q.push(i);
                pre[i]=now;
                vis[i]=min(vis[now], cap[now][i]-flow[now][i]);
                if(i==t)    return true;    //找到了 
            }
        }
    }
    return false;
}
int max_flow(int s,int t)
{
    int ans=0;
 
    while(bfs(s,t))
    {
        //这个for循环的作用就是找到一条到达重点的路中,最小的剩余流量值
//      int delta=0x7fffffff;
//      for(int i=t;i!=s;i=pre[i])
//      {
//          delta=min(delta,cap[pre[i]][i]-flow[pre[i]][i]);
//      }
        for(int i=t;i!=s;i=pre[i])
        {
//          flow[pre[i]][i]+=delta;
//          flow[i][pre[i]]-=delta;
            flow[pre[i]][i]+=vis[t];
            flow[i][pre[i]]-=vis[t];
        }
        ans+=vis[t];    //这是一个结论 记住就行 
    }
    return ans;
}
int main()
{
    cin>>m>>n;
    for(int i=1;i<=m;i++)
    {
        int x,y,rl;
        cin>>x>>y>>rl;
        //必须是+= 超级阴人.....没有看到一处到另一处不止一条排水沟 
        cap[x][y]+=rl;
        cap[y][x]+=rl;
        flow[x][y]=0;
        flow[y][x]+=rl;
    }
    cout<<max_flow(1,n);
    return 0;
}
//下面的代码是自己对《算法竞赛入门经典》中关于最大流的写法
//因为这个题中,两个点之间不仅只有一条路,所以开始使用邻接矩阵,然后再使用加边函数来进行操作
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=300;
struct Edge{
    int from, to, cap, flow;
    Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f){}
};
vector<Edge> edges;
vector<int> G[maxn];//邻接表,G[i][j],表示结点i的第j条边在edges[j]中。
int vis[maxn], pre[maxn], cap[205][205];//pre用来记录路径
int n, m;
void init()
{
    for(int i=0; i<=n; i++) G[i].clear();
    edges.clear();
}
inline void addedge(int from, int to, int cap) //这里使用了inline函数,一定条件下可以减少运行时间
{
    edges.push_back(Edge(from, to, cap, 0));
    edges.push_back(Edge(to, from, cap, cap));
    int m=edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}
bool bfs(int s, int t)
{
    memset(vis, 0,sizeof(vis));
    queue<int> Q;
    Q.push(s);
    vis[s]=inf;
    while(!Q.empty())
    {
        int x=Q.front(); Q.pop();
        for(int i=0; i<G[x].size(); i++)
        {
            Edge &e=edges[G[x][i]];
            if(!vis[e.to] && e.cap > e.flow)
            {
                pre[e.to]=G[x][i];
                vis[e.to]=min(vis[x], e.cap-e.flow);
                Q.push(e.to);
            }
        }
        if(vis[t])  return true;
    }
    return false;
}
int maxflow(int s, int t)
{
    int flow = 0;
    while(bfs(s, t))
    {
        for(int u=t; u!=s; u=edges[pre[u]].from)
        {
            edges[pre[u]].flow += vis[t];
            edges[pre[u]^1].flow -= vis[t];
        } 
        flow += vis[t];
    }
    return flow;
}
int main()
{
    int x, y, rl;
    scanf("%d%d", &m, &n);
    memset(cap, 0, sizeof(cap));
    for(int i=1; i<=m; i++)
    {
        scanf("%d%d%d", &x, &y, &rl);
        cap[x][y]+=rl;
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            if(cap[i][j]!=0)
                addedge(i, j, cap[i][j]);
        }
    }
    printf("%d\n", maxflow(1, n));
    return 0;
 } 

Guess you like

Origin www.cnblogs.com/alking1001/p/12068694.html