题解Luogu P3931 SAC E#1 - 一道难题 Tree

Posted JSOI爆零珂学家yzhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解Luogu P3931 SAC E#1 - 一道难题 Tree相关的知识,希望对你有一定的参考价值。

原题传送门

题目几乎告诉你要用最大流

先进行搜索,将树的叶子节点都连到一个虚拟点T上,流量为inf(这样不会干扰到前面部分的最大流)

其他边按树的形态连边,以根节点为S,跑一变最大流即可求出答案

#include <bits/stdc++.h>
#define N 100005
#define M 200005
#define inf (1<<30)
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf; 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int Min(register int a,register int b)
{
    return a<b?a:b;
}
struct node{
    int to,next,v;
}e[M<<1];
int head[N],cnt=1;
inline void add(register int u,register int v,register int val)
{
    e[++cnt]=(node){v,head[u],val};
    head[u]=cnt;
}
int n,s,t,maxflow=0;
inline void dfss(register int fa,register int u)
{
    bool f=false;
    for(register int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==fa)
            continue;
        f=true;
        dfss(u,v);
    }
    if(!f)
        add(u,t,inf),add(t,u,0);
}
int dep[N],gap[N],cur[N];
inline void bfs()
{
    memset(dep,-1,sizeof(dep));
    memset(gap,0,sizeof(gap));
    dep[t]=0;
    ++gap[dep[t]];
    queue<int> q;
    q.push(t);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(register int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(dep[v]!=-1)
                continue;
            q.push(v);
            dep[v]=dep[u]+1;
            ++gap[dep[v]];
        }
    }
}
inline int dfs(register int u,register int flow)
{
    if(u==t)
    {
        maxflow+=flow;
        return flow;
    }
    int used=0;
    for(register int i=cur[u];i;i=e[i].next)
    {
        cur[u]=i;
        int v=e[i].to;
        if(e[i].v&&dep[v]+1==dep[u])
        {
            int tmp=dfs(v,Min(e[i].v,flow-used));
            if(tmp)
            {
                used+=tmp;
                e[i].v-=tmp;
                e[i^1].v+=tmp;
            }
            if(used==flow)
                return used;
        }
    }
    --gap[dep[u]++]==0?dep[s]=n+1:++gap[dep[u]];
    return used;
}
inline void ISAP()
{
    maxflow=0;
    bfs();
    while(dep[s]<n)
    {
        memcpy(cur,head,sizeof(head));
        dfs(s,inf);
    }
}
int main()
{
    n=read(),s=read();
    t=n+1;
    for(register int i=1;i<n;++i)
    {
        int u=read(),v=read(),val=read();
        add(u,v,val),add(v,u,val);
    }
    dfss(0,s);
    ++n;
    ISAP();
    write(maxflow);
    return 0;
}

以上是关于题解Luogu P3931 SAC E#1 - 一道难题 Tree的主要内容,如果未能解决你的问题,请参考以下文章

题解Luogu P3931 SAC E#1 - 一道难题 Tree

[洛谷P3931]SAC E#1 - 一道难题 Tree

P3931 SAC E#1 - 一道难题 Tree

Luogu P3928 SAC E#1 - 一道简单题 Sequence2

洛谷 P3927 SAC E#1 - 一道中档题 Factorial 题解

luogu P3928 SAC E#1 - 一道简单题 Sequence2