luogu 1344

Posted zhangleo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu 1344相关的知识,希望对你有一定的参考价值。

首先题意就是裸的最小割啦

然后考虑如何统计边数

这里有一个trick:

我们设定一个大于$m$的阈值,对于每条边的边权我们乘这个阈值+1后跑最小割,得到的答案除以阈值就是真正的最小割,取模阈值后就是最少割掉的边数

为什么?

我们考虑:设原来的最小割割掉的边权为$v_1,v_2...v_n$,那么乘阈值+1后割掉的边权就是$v_1*lim+1,v_2*lim+1...v_n*lim+1$

也就是$lim(v_1+v_2+...+v_n)+n$

注意到$lim$大于边权,因此我们直接跑出最小割分解就是答案

而且显然,加一不会影响最小割的正确性

贴代码:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
using namespace std;
const ll lim=5000;
const ll inf=0x3f3f3f3f3f3f3f3fll;
struct Edge

    int nxt;
    int to;
    ll val;
edge[2005];
int head[50];
int dis[50];
int cur[50];
int cnt=1;
int n,m;
void add(int l,int r,ll w)

    edge[cnt].nxt=head[l];
    edge[cnt].to=r;
    edge[cnt].val=w;
    head[l]=cnt++;

void dadd(int l,int r,ll w)

    add(l,r,w),add(r,l,0);

int ide(int x)

    return x&1?x+1:x-1;

bool bfs()

    memcpy(cur,head,sizeof(head));
    memset(dis,0,sizeof(dis));
    dis[1]=1;
    queue <int> M;
    M.push(1);
    while(!M.empty())
    
        int u=M.front();
        M.pop();
        for(int i=head[u];i;i=edge[i].nxt)
        
            int to=edge[i].to;
            if(!dis[to]&&edge[i].val)dis[to]=dis[u]+1,M.push(to);
        
        
    return dis[n];

ll dfs(int x,ll lim)

    if(x==n)return lim;
    ll ret=0;
    for(int i=cur[x];i;i=edge[i].nxt)
    
        cur[x]=i;
        int to=edge[i].to;
        if(edge[i].val&&dis[to]==dis[x]+1)
        
            ll temp=dfs(to,min(lim,edge[i].val));
            if(temp)
            
                ret+=temp;
                lim-=temp;
                edge[i].val-=temp;
                edge[ide(i)].val+=temp;
                if(!lim)return ret;
            
        
    
    return ret;

ll dinic()

    ll ans=0;
    while(bfs())ans+=dfs(1,inf);
    return ans;

int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    
        int x,y;
        ll z;
        scanf("%d%d%lld",&x,&y,&z);
        z=z*lim+1;
        dadd(x,y,z);
    
    ll s=dinic();
    printf("%lld %lld\n",s/lim,s%lim);
    return 0;

 

以上是关于luogu 1344的主要内容,如果未能解决你的问题,请参考以下文章

luogu 1344 追查坏牛奶(最小割)

题解Luogu P1344 [USACO4.4]追查坏牛奶Pollutant Control

P3885方程的解(较详细)

LUOGU P1072

[luogu4556]雨天的尾巴

(luogu题解搬运系列)luogu p2651 添加括号Ⅲ