zoukankan      html  css  js  c++  java
  • POJ 3585

    http://poj.org/problem?id=3585

    题目

    有棵无根树,给出每一条边的最大流量,可以得到以点i为源时流过每个点的最大流量,可以随意调整i,求整个树所有的点的流量中的最大值。

    题解

    从每个点出发,发出的流量不好计算,因为有后效性。任意选一个根,如果从叶子出发,设dp[x]为以x为源时,x的流量,那么

    x为叶子时dp[x]=0

    考虑x的儿子t

    如果不是叶子,$dp[x]+=min(dp[t],v(x,t)$

    如果是叶子,$dp[x]+=v(x,t)$

    然后还需要换根,设以x为根的流量是f[x]

    每次换根

    $f[t]=dp[t]+f[x]-min(dp[t],v(x,t)$

    但是如果x在换了以后变成叶子也需要单独考虑

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<cassert>
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
    using namespace std;
    #define MAXN 200007
    int hd[MAXN], nxt[MAXN*2], to[MAXN*2], v[MAXN*2], en;
    int deg[MAXN];
    int dp[MAXN], f[MAXN];
    bool vis[MAXN];
    int n;
    inline void adde(int a, int b, int c) {
    	nxt[en]=hd[a]; hd[a]=en; to[en]=b; v[en]=c; en++;
    }
    void calc(int x) {
    	dp[x]=0;
    	vis[x]=1;
    	for(int i=hd[x]; ~i; i=nxt[i]) {
    		int t=to[i];
    		if(!vis[t]) {
    			if(deg[t]==1) {
    				dp[t]=0;
    				vis[t]=1;
    				dp[x] += v[i];
    			} else {
    				calc(t);
    				dp[x] += min(dp[t], v[i]);
    			}
    		}
    	}
    }
    void dfs(int x) {
    	vis[x]=1;
    	for(int i=hd[x]; ~i; i=nxt[i]) {
    		int t=to[i];
    		if(!vis[t]) {
    			if(deg[x]==1) {
    				f[t]=dp[t]+v[i];
    			} else {
    				f[t]=dp[t]+min(f[x]-min(dp[t],v[i]), v[i]);
    			}
    			dfs(t);
    		}
    	}
    }
    int main() {
    	int T; scanf("%d", &T);
    	while(0<T--) {
    		en=0;
    		scanf("%d", &n);
    		memset(hd+1, -1, sizeof(int)*n);
    		memset(deg+1, 0, sizeof(int)*n);
    		REP(i,1,n) {
    			int a,b,c; scanf("%d%d%d", &a, &b, &c);
    			adde(a,b,c); adde(b,a,c);
    			deg[a]++, deg[b]++;
    		}
    		memset(vis+1, 0, sizeof(bool)*n);
    		calc(1);		
    		memset(vis+1, 0, sizeof(bool)*n);
    		f[1]=dp[1];
    		dfs(1);
    		int ans=dp[1];
    		REPE(i,2,n) if(f[i]>ans) ans=f[i];
    		printf("%d
    ", ans);
    	}
    }
    
  • 相关阅读:
    剑指offer-第二章排序之年龄排序
    剑指offer—第二章算法之快速排序
    java小程序(课堂作业02)
    关于java的一些小知识(课程作业01)
    Java从命令行接受多个数字并求和
    《大道至简》第一章读后感及伪代码
    大道至简读后感
    GCPC 2013_A Boggle DFS+字典树 CSU 1457
    Aizu 2155 Magic Slayer 背包DP
    UVALive 4255 Guess
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12469911.html
Copyright © 2011-2022 走看看