zoukankan      html  css  js  c++  java
  • 洛谷 P3128 最大流Max Flow

    同步:https://buringstraw.win/index.php/archives/39/

    P3128 [USACO15DEC]最大流Max Flow

    题面

    题目描述

    FJ给他的牛棚的N(2≤N≤50,000)个隔间之间安装了N-1根管道,隔间编号从1到N。所有隔间都被管道连通了。

    FJ有K(1≤K≤100,000)条运输牛奶的路线,第i条路线从隔间si运输到隔间ti。一条运输路线会给它的两个端点处的隔间以及中间途径的所有隔间带来一个单位的运输压力,你需要计算压力最大的隔间的压力是多少。

    输入输出格式

    输入格式:

    The first line of the input contains NNN and KKK.

    The next N−1N-1N−1 lines each contain two integers xxx and yyy (x≠yx e yx≠y) describing a pipe

    between stalls xxx and yyy.

    The next KKK lines each contain two integers sss and ttt describing the endpoint

    stalls of a path through which milk is being pumped.

    输出格式:

    An integer specifying the maximum amount of milk pumped through any stall in the barn.

    输入输出样例

    输入样例#1:

    5 10
    3 4
    1 5
    4 2
    5 4
    5 4
    5 4
    3 5
    4 3
    4 3
    1 3
    3 5
    5 4
    1 5
    3 4
    

    输出样例#1:

    9
    

    Solve

    树上差分模板题。

    好难,做了一下午

    (树咋存来着?)

    一开始觉得前向星来存树不好找爸爸。折腾了半天还是用了前向星。

    然后LCA也忘了。我还非常沙雕地用tarjan求出每两个点之间的LCA,还开小了数组。结果TLE+MLE。

    TLE+MLE

    改用倍增求一直不过样例,后来才发现我一直用的存父亲的数组是放在tarjan LCA里求的。。。

    接着只过了一两个点的原因竟然是:

    int getLca(int p1,int p2) {
        if(depth[p1]<depth[p2]){p1^=p2;p2^=p1;p1^=p2;}
        for(int i=H;i>=0;--i){
            if(depth[f[p1][i]]>=depth[p2])p1=f[p1][i];}
        if(p1==p2)return p1;
        for(int i=H;i>=0;--i)
            if(f[p1][i]!=f[p2][i]){
                p1=f[p1][i];
                p2=f[p2][i];}
        /*没错就是这里!!!!!*/
        return p1;
        //应该是return f[p1][0];
    }
    

    差错的时候写了dfs和bfs两种初始化方法,现在都能AC。

    完整代码如下

    #include<cstdio> 
    #include<iostream>
    #include<utility>
    #include<map>
    #include<cstring>
    #include<cmath>
    using namespace std;
    
    const int MAXN=2e5+5;
    
    struct ed
    {
    	int to,nex,w;
    } e[MAXN];
    
    int head[MAXN];
    int dad[MAXN];//树的 
    bool v[MAXN];
    int yaLi[MAXN];
    
    int depth[MAXN];//深度
    int f[MAXN][16];//for 倍增 
    int H;
    
    int maxYaLi=0;
    int root=1,newp;
    
    map<pair<int,int>,int> zuzong;
    
    int n,k;
    
    void vAdd(int x,int y);
    void doUnion(int x,int y);
    void doInit(void);
    void lca(int p);
    void getMax(int p);
    void bfs(int root);
    void dfs(int p,int fat);
    int doFind(int x);
    int readLca(int p1,int p2);
    int getLca(int p1,int p2);
    
    int main(void)
    {
    	scanf("%d%d",&n,&k);
    	H=1.0*log(n)/log(2);
    	for(int i=1;i<n;++i)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		vAdd(x,y);
    		vAdd(y,x);
    	}
    	bfs(1);
    	//或dfs(1,0); 
    	for(int i=1;i<=k;++i)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		int lca=getLca(x,y);
    		++yaLi[x];
    		++yaLi[y];
    		--yaLi[lca];
    		--yaLi[f[lca][0]];
    	}
    	memset(v,0,sizeof(v));
    	getMax(1);
    	printf("%d
    ",maxYaLi);
    	return 0;
    }
    
    void vAdd(int x,int y)
    {
    	++newp;
    	e[newp].to=y;
    	e[newp].nex=head[x];
    	head[x]=newp;
    }
    
    
    void getMax(int p)
    {
    	v[p]=1;
    	for(int i=head[p];i;i=e[i].nex)
    	{
    		int y=e[i].to;
    		if(v[y])continue;
    		else
    		{
    			getMax(y);
    			yaLi[p]+=yaLi[y];
    		}
    	}
    	maxYaLi=max(maxYaLi,yaLi[p]);
    }
    
    int getLca(int p1,int p2) 
    {
    	if(depth[p1]<depth[p2])
    	{
    		p1^=p2;//交换值 
    		p2^=p1;
    		p1^=p2;
    	}
    	for(int i=H;i>=0;--i)
    	{
    		if(depth[f[p1][i]]>=depth[p2])
    		{
    			p1=f[p1][i];
    		}
    	}
    	if(p1==p2)return p1;
    	for(int i=H;i>=0;--i)
    	{
    		if(f[p1][i]!=f[p2][i])
    		{
    			p1=f[p1][i];
    			p2=f[p2][i];
    		}
    	}
    	return f[p1][0];
    }
    
    #include<queue>
    void bfs(int root)
    {
    	queue<int> q;
    	q.push(root);
    	depth[root]=1;
    	v[root]=1;
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop(); 
    		for(int i=head[u];i;i=e[i].nex)
    		{
    			int y=e[i].to;
    			if(v[y])continue;
    			else
    			{
    				v[y]=1;
    				depth[y]=depth[u]+1;
    				f[y][0]=u;
    				for(int j=1;j<=H;++j)
    				{
    					f[y][j]=f[f[y][j-1]][j-1];
    				}
    				q.push(y);
    			}
    		}
    	}
    }
    
    void dfs(int p,int fat)
    {
    	depth[p]=depth[fat]+1;
    	f[p][0]=fat;
    	for(int i=1;i<=H;++i)
    	{
    		f[p][i]=f[f[p][i-1]][i-1];
    	}
    	for(int i=head[p];i;i=e[i].nex)
    	{
    		int y=e[i].to;
    		if(y==fat)continue;
    		else dfs(y,p);
    	}
    }
    

    还有一份41分代码(Tarjan)

    #include<cstdio> 
    #include<iostream>
    #include<utility>
    #include<map>
    #include<cstring>
    using namespace std;
    
    const int MAXN=5e4+5;
    
    struct ed
    {
        int to,nex,w;
    } e[MAXN];
    
    int head[MAXN];
    int fa[MAXN];//并查集的 
    int dad[MAXN];//树的 
    bool v[MAXN];
    int yaLi[MAXN];
    int maxYaLi=0;
    int root=1,newp;
    
    map<pair<int,int>,int> zuzong;
    
    int n,k;
    
    void vAdd(int x,int y);
    void doUnion(int x,int y);
    void doInit(void);
    int doFind(int x);
    void lca(int p);
    int readLca(int p1,int p2);
    void getMax(int p);
    
    int main(void)
    {
        scanf("%d%d",&n,&k);
        doInit();
        for(int i=1;i<n;++i)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            vAdd(x,y);
            vAdd(y,x);
        }
        lca(1);
        for(int i=1;i<=k;++i)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int lca=readLca(x,y);
            ++yaLi[x];
            ++yaLi[y];
            --yaLi[lca];
            --yaLi[dad[lca]];
        }
        memset(v,0,sizeof(v));
        getMax(1);
        printf("%d
    ",maxYaLi);
        return 0;
    }
    
    void vAdd(int x,int y)
    {
        ++newp;
        e[newp].to=y;
        e[newp].nex=head[x];
        head[x]=newp;
    }
    
    void doInit(void)
    {
        for(int i=1;i<=n;++i)
        {
            fa[i]=i;
        }
    }
    
    void doUnion(int x,int y)
    {
        x=doFind(x);
        y=doFind(y);
        fa[x]=y;
    }
    
    int doFind(int x)
    {
        if(fa[x]==x)return x;
        else return fa[x]=doFind(fa[x]);
    }
    
    void lca(int u)
    {
        v[u]=1;
        for(int i=head[u];i;i=e[i].nex)
        {
            int y=e[i].to;
            if(v[y])continue;
            else
            {
                dad[y]=u;
                lca(y);
                doUnion(y,u);
            }
        }
        for(int i=1;i<=n;++i)
        {
            if(i==u)continue;
            else
            {
                if(v[i])
                {
                    zuzong[make_pair(u,i)]=doFind(i);
                }
            }
        }
    }
    
    int readLca(int p1,int p2)
    {
        pair<int,int> pa=make_pair(p1,p2),pb=make_pair(p2,p1);
        int z1=zuzong[pa];
        if(z1)return z1;
        else return zuzong[pb];
    }
    
    void getMax(int p)
    {
        v[p]=1;
        for(int i=head[p];i;i=e[i].nex)
        {
            int y=e[i].to;
            if(v[y])continue;
            else
            {
                getMax(y);
                yaLi[p]+=yaLi[y];
            }
        }
        maxYaLi=max(maxYaLi,yaLi[p]);
    }
    
  • 相关阅读:
    Cuckoo for Hashing_双哈希表
    nyoj113_字符串替换
    nyoj366_D的小L_字典序_全排列
    二叉树的前序 中序 后序 遍历(递归/非递归)
    Java 学习路线
    leetcode 04 Median of Two Sorted Arrays
    ThreadLocal 的机制与内存泄漏
    try finally 执行顺序问题
    Java中的类加载器
    快速理解Java中的七种单例模式
  • 原文地址:https://www.cnblogs.com/buringstraw/p/10805765.html
Copyright © 2011-2022 走看看