NC20210. [JSOI2015]SALESMAN
描述
输入描述
输入的第一行是一个正整数n(5 ≤ n ≤ 100000),表示城镇数目。城镇以1到n的数命名。小T的家乡命名为1。
第二行和第三行都包含以空格隔开的n-1个整数,第二行的第i个数表示在城镇 i+1停留的净收益。
第三行的第i个数表示城镇i+1规定的最大停留次数。
所有的最大停留次数都不小于2。接下来的n-1行每行两个1到n的正整数x,y,之间以一个空格 隔开,表示x,y之间有一条不经过其它城镇的双向道路。
输入数据保证所有城镇是连通的。
输出描述
输出有两行,第一行包含一个自然数,表示巡回旅行的最大收益。
如果该方案唯一,在 第二行输出“solution is unique”,否则在第二行输出“solution is not unique”。
示例1
输入:
9 -3 -4 2 4 -2 3 4 6 4 4 2 2 2 2 2 2 1 2 1 3 1 4 2 5 2 6 3 7 4 8 4 9
输出:
9 solution is unique
说明:
最佳路线包括城镇 1,2, 4, 5, 9。C++11(clang++ 3.9) 解法, 执行用时: 64ms, 内存消耗: 3684K, 提交时间: 2019-03-16 12:45:13
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int N=100005; int cnt,n,val[N],lim[N],last[N],a[N],a1,f[N],g[N]; struct edge{int to,next;}e[N*2]; void addedge(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; } bool cmp(int a,int b) { return f[a]>f[b]; } void dfs(int x,int fa) { f[x]=val[x]; for (int i=last[x];i;i=e[i].next) if (e[i].to!=fa) dfs(e[i].to,x); a1=0; for (int i=last[x];i;i=e[i].next) if (e[i].to!=fa) a[++a1]=e[i].to; sort(a+1,a+a1+1,cmp); int p=0; while (p<min(lim[x]-1,a1)&&f[a[p+1]]>=0) p++,f[x]+=f[a[p]],g[x]|=g[a[p]]; if (p<a1&&p>0&&f[a[p]]==f[a[p+1]]||f[a[p]]==0&&p>0) g[x]=1; } int main() { scanf("%d",&n); for (int i=2;i<=n;i++) scanf("%d",&val[i]); for (int i=2;i<=n;i++) scanf("%d",&lim[i]); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y); } lim[1]=n+1; dfs(1,0); printf("%d\n",f[1]); if (g[1]) printf("solution is not unique"); else printf("solution is unique"); return 0; }