David与Vincent的博弈游戏[树型DP]
生活随笔
收集整理的這篇文章主要介紹了
David与Vincent的博弈游戏[树型DP]
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
\(\mathcal{Description}\)
\(\mathcal{Solution}\)
根據題意,我們知道
根節點深度為1,深度為 奇數 的節點由\(David\)移動,我們稱為\(D\)點,深度為 偶數 的節點由\(Vincent\)移動,我們稱為\(V\)點
記\(big[i],sma[i]\)表示\(i\)節點以為根節點,由\(i\)開始移動,最后到葉子節點時的數字由\(David\)放數字 最大是第幾大的數字 ,由\(Vincent\)放數字__最小是第幾小的數字__
假如\(i\)節點是\(D\)點
那么對于\(i\)的兒子\(v\),有
- \(big[i]=min\{big[i],big[v]\}\)
因為\(David\)移動到葉子節點時盡量要最大的數字,顯然往兒子節點移動時,往到葉子節點時能得到最大數的排名最高的兒子移動最好,由于是\(David\)放數字,所以\(David\)不會將最優的數字浪費在他不會移動到的點 - \(sma[i]+=sma[v]\)
我們知道\(sma[v]\),若由\(D\)向\(V\)移動,那么此時\(sma[i]\)就至少是\(sma[v]\)
若\(D\)向另外的兒子\(V'\)移動,考慮為什么不往\(V\)移動:
因為向\(V\)移動后\(Vincent\)肯定會盡量使結果對其最優,所以\(Vincent\)會把對他而言最優的數字放在那邊,聰明的\(David\)發現后就不會往這邊走了,那為什么要把最優數字放在\(V\)呢,同理,\(David\)會發現往其他地方移動沒有往\(V\)更優,就會往\(V\)移動了,而為什么\(Vincent\)要讓\(David\)只能往\(V'\)移動呢,因為如果\(Vincent\)讓\(David\)往\(V\)移動的話得到的最終結果對\(Vincent\)就不是最優的了。這么說可能有點繞,但都是必然的因果關系,主要我們要在為\(David\)考慮時,還要換位思考\(Vincent\)的想法,可以畫個圖想想。
所以\(David\)會把最優的一些數字放在\(V\)之類的其他點,而這樣\(Vincent\)就會往\(V'\)走,所以就會浪費掉除\(sma[v']\)以外個\(sma[v]\)個大數字,又此時往\(V'\)移動得到的最優數字是第\(big[v']\),所以要加上所有兒子的\(sma\)
假如\(i\)節點是\(V\)點
那么此時的情況和\(D\)點相反,因為他們的目的相反,所以
對于\(i\)的兒子\(v\)有
- \(big[i]+=big[v]\)
- \(sma[i]=min\{sma[i],sma[v]\}\)
代碼
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年06月20日 星期四 15時27分03秒
*******************************/
#include <cstdio>
#include <fstream>
using namespace std;
const int maxn = 100005;
//{{{cin 快讀
struct IO{template<typename T>IO & operator>>(T&res){res=0;bool flag=false;char ch;while((ch=getchar())>'9'||ch<'0') flag|=ch=='-';while(ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();if (flag) res=~res+1;return *this;}
}cin;
//}}}
int n,m,u,v,root,cnt;
int head[maxn],to[maxn],nxt[maxn];
int big[maxn],sma[maxn],fa[maxn],col[maxn];//col[i]=1 -> David
//{{{add
void add (int u,int v)
{nxt[++cnt]=head[u],head[u]=cnt,to[cnt]=v,fa[v]=u;
}
//}}}
void dfs (int x)
{col[x]=!col[fa[x]];if (!head[x]){++m;big[x]=sma[x]=1;return;}if (col[x]) big[x]=n+1;else sma[x]=n+1;for (int e=head[x];e;e=nxt[e]){dfs(to[e]);if (col[x]){big[x]=min(big[x],big[to[e]]);sma[x]+=sma[to[e]];}else{big[x]+=big[to[e]];sma[x]=min(sma[x],sma[to[e]]);}}
}
int main()
{cin>>n;for (int i=1;i<=n-1;++i){cin>>u>>v;add(u,v);}for (int i=1;i<=n&&!root;++i)if (!fa[i]) root=i;dfs(root);printf("%d %d\n",m-big[root]+1,sma[root]);return 0;
}
轉載于:https://www.cnblogs.com/Morning-Glory/p/11066909.html
總結
以上是生活随笔為你收集整理的David与Vincent的博弈游戏[树型DP]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《学习之道》第十三章自己也要总结
- 下一篇: 使用SSH和Nginx做内网HTTP映射