洛谷 P1345

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40924940/article/details/84335027

这道题 很有意思

这里的割不是线了 是点,这题比较麻烦的是建图

用一下网上大牛的图,附博客链接:https://www.luogu.org/space/show?uid=25630

有了这个图,整个题就显得简单很多了,

我们把一个点 拆成两个,一个是 i 另一个是 i + n ,这两点之间肯定先连上,之后对与一个点分成的两个点,我们去以此把无向图变成一个有向图,当然这道题里所有的边容量完全就是 无穷大 ,然后某点分成的两个点之间 边的容量设为 1 ,这样我们去割的时候计算出来的最小割就是我们要切断的点了,当然 别忘记反向边也需要初始化。需要注意的就是 我们输入 x y 的时候

链接的 是 x+n 和 y ,x 和 x+n 相连,起始点也不再是 s 而是 s + n了。。看图就感觉出来了。。。

然后根据最小割最大流相等,求一下最大流 就算出最小割了。

以下为 AC 代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 2005;
const int INF = 0x3f3f3f3f;
int head[maxn*2],num;
struct node
{
    int val;
    int nex,to;
}ed[maxn*2];
void add(int u,int v,int w)
{
    ed[++num].to = v;
    ed[num].val = w;
    ed[num].nex = head[u];
    head[u] = num;
}
int h[maxn*2];
int st,en;
int n,m;
bool bfs()
{
    queue<int> q;
    memset(h,-1,sizeof(h));
    h[st]=0,q.push(st);
    while(q.size())
    {
        int u = q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=ed[i].nex)
        {
            int v = ed[i].to;
            if(h[v] == -1 && ed[i].val)
            {
                h[v] = h[u] + 1;
                if(v == en)
                    return true;
                q.push(v);
            }
        }
    }
    return false;

}
int dfs(int u, int val)
{
     int add = 0;
     if(u == en)
        return val;
     for(int i=head[u];i!=-1;i=ed[i].nex)
     {
         int v = ed[i].to;
         if(h[v] == h[u] + 1 && ed[i].val)
         {
             int k = dfs(v, min(val - add, ed[i].val));
             if(!k)
                h[v] = -1;
             add += k;
             ed[i].val -= k;
             ed[i ^ 1].val += k;
         }
     }
     return add;
}
int dinic()
{
    int ans = 0;
    while(bfs())
    {
        ans += dfs(st, INF);
    }
    return ans;
}
int main()
{
    cin>>n>>m>>st>>en;
    st += n;
    num = -1;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=n;i++)
    {
        add(i, i+n, 1);
        add(i+n, i, 0);
    }
    int x,y;
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y;
        add(x+n, y, INF);
        add(y, x+n, 0);
        add(y+n, x, INF);
        add(x, y+n, 0);
    }
    printf("%d\n",dinic());
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40924940/article/details/84335027