P1453 城市环路
题目背景
一座城市,往往会被人们划分为几个区域,例如住宅区、商业区、工业区等等。B市就被分为了以下的两个区域——城市中心和城市郊区。在着这两个区域的中间是一条围绕B市的环路,环路之内便是B市中心。
题目描述
整个城市可以看做一个N个点,N条边的单圈图(保证图连通),唯一的环便是绕城的环路。保证环上任意两点有且只有2条路径互通。图中的其它部分皆隶属城市郊区。
现在,有一位名叫Jim的同学想在B市开店,但是任意一条边的2个点不能同时开店,每个点都有一定的人流量Pi,在该点开店的利润就等于该店的人流量Pi×K(K≤10000),K的值将给出。
Jim想尽量多的赚取利润,请问他应该在哪些地方开店?
输入输出格式
输入格式:
第一行一个整数N 代表城市中点的个数。城市中的N个点由0~N-1编号。
第二行N个正整数,表示每个点的人流量Pi(Pi≤10000)。
下面N行,每行2个整数A,B,表示A,B建有一条双向路。
最后一行一个实数K。
输出格式:
一个实数M,(保留1位小数),代表开店的最大利润。
输入输出样例
说明
【数据范围】
对于20%的数据,N≤100.
对于另外20%的数据,环上的点不超过2000个
对于50%的数据 N≤50000.
对于100%的数据 N≤100000.
//一道上午的时候不知道哪错了发了讨论然后放弃了的题。 //感谢@sqairy 大佬 一语道破我的错误所在 //楼下都用的dfs找环,当时没想出用dfs做来,所以在输入的时候处理的环 //因为如果一条边的端点已经全部出现的话,我们把这条边加进去,就构成了一个环, //所以开一个flag[]标记,标记这个点有没有输入过, //如果 flag[u]&&flag[v],那么这肯定是一个环上的一条边,然后让A=u,B=v, //并且我们不把这条边加进图里,这样就构成了一棵树 //从A,B做两次树形DP,找最大值。 和没有上司的舞会那道题一样 //还有就是要取max(dp[A][0],dp[B][0]), //为什么是不选A和B的情况的最大值: //因为我们如果是在选A或B的情况中取最大值,我们不能保证A(B)选了,但是B(A)没选 #include<iostream> #include<cstdio> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int N=1e6+5; int n,A,B; double K; int p[N]; int head[N],num_edge; bool flag[N]; double dp[N][2]; struct Edge { int v,nxt; }edge[N<<1]; int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } void add_edge(int u,int v) { edge[++num_edge].v=v; edge[num_edge].nxt=head[u]; head[u]=num_edge; } void dfs(int u,int fa) { dp[u][1]=p[u],dp[u][0]=0; for(int i=head[u],v;i;i=edge[i].nxt) { v=edge[i].v; if(v==fa) continue; dfs(v,u); dp[u][0]+=max(dp[v][0],dp[v][1]); //这个点不选,加上它的儿子选或不选的最大值 dp[u][1]+=dp[v][0]; //这个点选,它的儿子们不能选 } } int main() { n=read(); for(int i=0;i<n;++i) p[i]=read(); bool ok=0; //标记找没找到环 for(int i=1,u,v;i<=n;++i) { u=read(),v=read(); if(!ok&&flag[u]&&flag[v]) //一条边的两个端点都出现过,那么着肯定是一个环上的边 { ok=1; //找到环了 A=u,B=v; //记录两个端点 continue; //不加这条边 } flag[u]=flag[v]=1; //标记两个端点已经出现过 add_edge(u,v); //加边 add_edge(v,u); } scanf("%lf",&K); dfs(A,A); //从A跑DFS double ans=dp[A][0]; dfs(B,B); //从B跑DFS ans=max(ans,dp[B][0]); printf("%.1lf",ans*K); return 0; }