zoukankan      html  css  js  c++  java
  • P3128 [USACO15DEC]最大流Max Flow

    P3128 [USACO15DEC]最大流Max Flow

    对,这是一道最大流的题目qwq

    树上跑最大流,没错

    也就是跑最小割

    你看名字里都有最大流,为什么不能跑最大流qwq..............................
    编不下去了

    跑树上差分。

    就像数组上可以进行差分一样,树上也可以进行差分。适用于树上两点之间的路径操作,和极少数的查询

    适用于维护路径长可以进行结合律的操作

    比如说我们要在树上进行两点之间的路径上的节点值加一个数,最后输出所有节点值之和。

    我们可以进行树链剖分,可是使用树链剖分有些大材小用了,而且常数巨大

    我们就可以使用差分

    比如说这么一棵树

    我们要使得8到11的路径上的点加3

    我们就可以设一个数组,(t[i])表示这棵树的差分数组,(st[i][j])表示树上的倍增数组

    然后我们令(t[8]+=3,t[11]+=3,t[lca_{(8,11)}]-=3,t[st[lca_{(8,11)}][0]]-=3)

    然后我们将差分数组使用以下程序进行整理整理,然后进行查询。

    
    void DFS(int now,int fa)
    {
    	int pas=0;
    	for(int i=head[now];i;i=line[i].nxt)
    		if(line[i].p!=fa)
    		{
    			DFS(line[i].p,now);
    			t[now]+=t[line[i].p];
    		}
    }
    

    将所有点上的值递归加起来,就成了下图的情况。成功实现了O(1)修改,O(N)查询


    而对于维护边权呢?我们可以将边权下放至所连点中深度最深的点上去

    然后将差分时的(t[st[lca_{(a,b)}][0]]-=add,t[lca_{(a,b)}]-=add)变为(t[lca_{(a,b)}]-add*2)就可以了,树链剖分也可以将边权下放至点

    此题(code)

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using std::swap;
    using std::max;
    const int maxn=50100;
    struct node
    {
    	int p;
    	int nxt;
    };
    node line[maxn<<1];
    int head[maxn],tail;
    void add(int a,int b)
    {
    	line[++tail].p=b;
    	line[tail].nxt=head[a];
    	head[a]=tail;
    }
    int st[maxn][20];
    int log[maxn];
    int dep[maxn];
    int ans,t[maxn];
    void dfs(int now,int fa)
    {
    	st[now][0]=fa;
    	dep[now]=dep[fa]+1;
    	for(int i=1;i<=log[dep[now]];i++)
    		st[now][i]=st[st[now][i-1]][i-1];
    	for(int i=head[now];i;i=line[i].nxt)
    		if(line[i].p!=fa)
    			dfs(line[i].p,now);
    }
    int lca(int a,int b)
    {
    	if(dep[a]<dep[b])	swap(a,b);
    	for(int i=log[dep[a]];i>=0;i--)
    		if(dep[st[a][i]]>=dep[b])
    			a=st[a][i];
    	if(a==b)	return a;
    	for(int i=log[dep[a]];i>=0;i--)
    		if(st[a][i]!=st[b][i])
    			a=st[a][i],b=st[b][i];
    	return st[a][0];
    }
    void DFS(int now,int fa)
    {
    	int pas=0;
    	for(int i=head[now];i;i=line[i].nxt)
    		if(line[i].p!=fa)
    		{
    			DFS(line[i].p,now);
    			t[now]+=t[line[i].p];
    		}
    	ans=max(ans,t[now]);
    }
    int main()
    {
    	int n,k;
    	scanf("%d%d",&n,&k);
    	for(int i=2;i<=n;i++)	log[i]=log[i>>1]+1;
    	int a,b;
    	for(int i=1;i<n;i++)
    	{
    		scanf("%d%d",&a,&b);
    		add(a,b);add(b,a);
    	}
    	dfs(1,0);
    	for(int i=1;i<=k;i++)
    	{
    		scanf("%d%d",&a,&b);
    		t[a]++;t[b]++;
    		int LCA=lca(a,b);
    		t[LCA]--;	
    		t[st[LCA][0]]--;
    	}
    	DFS(1,0);
    	printf("%d",ans);
    }
    
  • 相关阅读:
    VS2010 使用TeeChart画图控件
    程序猿接私活经验总结,来自csdn论坛语录
    锁(下)
    android4.4组件分析--service组件-bindService源代码分析
    黑客和敏捷开发
    编写你自己的单点登录(SSO)服务
    Cloudera impala简单介绍及安装具体解释
    ACdream群赛1112(Alice and Bob)
    八大排序算法总结
    垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
  • 原文地址:https://www.cnblogs.com/Lance1ot/p/9403259.html
Copyright © 2011-2022 走看看