2016年计蒜客初赛第六场 微软的员工福利(中等)

来源:互联网 发布:淘宝物品怎么靠前搜到 编辑:程序博客网 时间:2024/06/09 13:58

题目链接:点这里!!!!!


题解:dp(i,u)表示第i个人选第u个显示器为根的子树得到的最大值。然后去枚举i和他二子的最大值和最小值就可以了。

时间复杂度为O(n^3)


代码:

#include<cstdio>#include<cstring>#include<iostream>#include<sstream>#include<algorithm>#include<vector>#include<bitset>#include<set>#include<queue>#include<stack>#include<map>#include<cstdlib>#include<cmath>#define LL long long#define pb push_back#define pa pair<int,int>#define clr(a,b) memset(a,b,sizeof(a))#define lson lr<<1,l,mid#define rson lr<<1|1,mid+1,r#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)#define key_value ch[ch[root][1]][0]#pragma comment(linker, "/STACK:102400000000,102400000000")const LL  MOD = 1000000007;const int N = 100+15;const int maxn = 8e3+15;const int letter = 130;const LL INF = 1e18;const double pi=acos(-1.0);const double eps=1e-10;using namespace std;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int n;LL p[N][2],dp[N][2];int vis[N];vector<int>G[N],g[N];stack<int>s;queue<int>q;void bfs(int y){    while(!q.empty()) q.pop();    while(!s.empty()) s.pop();    q.push(y);    vis[y]=1;    while(!q.empty()){        int x=q.front();        q.pop();        s.push(x);        for(int i=0;i<G[x].size();i++){            int to=G[x][i];            if(!vis[to]){                g[x].pb(to);                vis[to]=1;                q.push(to);            }        }    }}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++){        scanf("%lld%lld",&p[i][0],&p[i][1]);        if(p[i][0]>p[i][1]) swap(p[i][0],p[i][1]);    }    for(int i=1;i<=n;i++)G[i].clear();    int x,y;    for(int i=0;i<n-1;i++){        scanf("%d%d",&x,&y);        G[x].pb(y),G[y].pb(x);    }    bfs(1);    LL max1=0,min1=0;    int c,d,e;    while(!s.empty()){        x=s.top(),s.pop();        if(g[x].size()==0){            dp[x][0]=p[x][0];            dp[x][1]=p[x][1];        }        else if(g[x].size()==1){            y=g[x][0];            for(int pd=0;pd<2;pd++){                max1=max(p[x][pd],p[y][0]);                min1=min(p[x][pd],p[y][0]);                LL p0=(max1-min1+999)/1000*666*x;                max1=max(p[x][pd],p[y][1]);                min1=min(p[x][pd],p[y][1]);                LL p1=(max1-min1+999)/1000*666*x;                if(dp[y][0]-p0>dp[y][1]-p1) dp[x][pd]=dp[y][0]-p0+p[x][pd];                else dp[x][pd]=dp[y][1]-p1+p[x][pd];            }        }        else {            dp[x][0]=dp[x][1]=-INF;            for(int pd=0;pd<2;pd++){                for(int u=0;u<2;u++)                for(int i=0;i<g[x].size();i++)                for(int v=0;v<2;v++)                for(int j=0;j<g[x].size();j++){                    if(i==j) continue;                    c=g[x][i],d=g[x][j];                    LL max1=max(p[c][u],p[d][v]);                    LL min1=min(p[c][u],p[d][v]);                    if(p[x][pd]<min1||p[x][pd]>max1) continue;                    LL ans=0;                    ans=ans+dp[c][u]+dp[d][v];                    ans=ans-(max1-min1+999)/1000*666*x;                    int flag=1;                    for(int k=0;k<g[x].size();k++){                        LL vs=-INF;                        if(i==k||j==k)continue;                        e=g[x][k];                        if(p[e][1]<min1||p[e][0]>max1||(p[e][0]<min1&&p[e][1]>max1)){flag=0;break;}                        if(min1<=p[e][0]&&p[e][0]<=max1) vs=dp[e][0];                        if(min1<=p[e][1]&&p[e][1]<=max1) vs=max(vs,dp[e][1]);                        ans+=vs;                    }                    if(!flag) continue;                    dp[x][pd]=max(dp[x][pd],ans+p[x][pd]);                }            }            for(int pd=0;pd<2;pd++){                for(int u=0;u<2;u++)                for(int i=0;i<g[x].size();i++){                    c=g[x][i];                    LL max1=max(p[c][u],p[x][pd]);                    LL min1=min(p[c][u],p[x][pd]);                    LL ans=dp[c][u];                    ans=ans-(max1-min1+999)/1000*666*x;                    int flag=1;                    for(int k=0;k<g[x].size();k++){                        LL vs=-INF;                        if(i==k)continue;                        e=g[x][k];                        if(p[e][1]<min1||p[e][0]>max1||(p[e][0]<min1&&p[e][1]>max1)){flag=0;break;}                        if(min1<=p[e][0]&&p[e][0]<=max1) vs=dp[e][0];                        if(min1<=p[e][1]&&p[e][1]<=max1) vs=max(vs,dp[e][1]);                        ans+=vs;                    }                    if(!flag) continue;                    dp[x][pd]=max(dp[x][pd],ans+p[x][pd]);                }            }        }    }    printf("%lld\n",max(dp[1][0],dp[1][1]));    return 0;}


0 0