贪心策略、深度优先搜索
网络流模型理论上可以解决此题,把除1和n以外的每个结点都拆成两个结点,中间用一条容量为1的边连接,结点1为源,结点n为汇求最大流。无奈本题数据规模较大,最多有5000个结点,而且边数未知。
注意到题目给出的图具有特殊的性质:边是按从东到西的顺序给出的,而且所有边不相交。这样我们可以采取如下贪心策略:用深度优先搜索从结点1出发找一条尽可能靠东(或尽可能靠西)的路径,让一个运动员沿此路径滑雪,把此路径上的除起点和终点外的所有结点从图中删去,然后重复此过程。这个策略显然正确,由于所有边都不相交,每次找最靠东(或最靠西)的路径可以给后面要找的路径腾出最大的空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #include <iostream> using namespace std; struct edge { int v; edge *next; edge(int v,edge *next):v(v),next(next) {} } *e[5005]; int n; bool u[5005]; bool dfs(int v) { if(v==n) return true; u[v]=true; for(edge *t=e[v];t;t=t->next) if(!u[t->v]&&dfs(t->v)) return true; return false; } int main() { freopen("nar.in","r",stdin); freopen("nar.out","w",stdout); scanf("%d",&n); int t,v,ans=0; for(int i=1;i<n;++i) for(scanf("%d",&t);t;--t) { scanf("%d",&v); e[i]=new edge(v,e[i]); } for(edge *p=e[1];p;p=p->next) if(!u[p->v]&&dfs(p->v)) ++ans; printf("%d\n",ans); return 0; } |
的积水,这时我们可以把
累加到答案中去,然后把
赋为
并把(x’,y’)看作边界格子。如果
,我们可以直接把(x’,y’)看作边界格子。当处理完所有(x,y)的相邻非边界格子后,把(x,y)从边界格子中删去。重复这个过程,直至边界格子集合为空为止。显然,用一个小根堆来维护边界格子集合是在适合不过了。
。
表示以v为根的子树中根结点v的颜色为c时的绿色结点数最大值。当v为叶结点时,
而
;当v为非叶结点时,我们要给v的孩子结点分配不同于c的颜色,并在所有方案中去最大值,还有不要忘记当c为0时把根结点v自己加进去。求最小值与之类似,只要把所有的max都变为min即可。