51nod 1299 监狱逃离 树形dp
生活随笔
收集整理的這篇文章主要介紹了
51nod 1299 监狱逃离 树形dp
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題意
監(jiān)獄有N條道路連接N + 1個(gè)交點(diǎn),編號0至N,整個(gè)監(jiān)獄被這些道路連在一起(任何2點(diǎn)之間都有道路),人們通過道路在交點(diǎn)之間走來走去。其中的一些交點(diǎn)只有一條路連接,這些點(diǎn)是監(jiān)獄的出口。在各個(gè)交點(diǎn)中有M個(gè)點(diǎn)住著犯人(M <= N + 1),剩下的點(diǎn)可以安排警衛(wèi),有警衛(wèi)把守的地方犯人無法通過。給出整個(gè)監(jiān)獄的道路情況,以及犯人所在的位置,問至少需要安排多少個(gè)警衛(wèi),才能保證沒有1個(gè)犯人能夠逃到出口,如果總有犯人能夠逃出去,輸出-1。
1<= N <= 100000
分析
據(jù)說直接上最小割可以艸過去。。。
找一個(gè)非葉節(jié)點(diǎn)當(dāng)根,就可以樹形dp。
設(shè)f[x,0]表示以x為根的樹,有犯人走上來且沒有到出口的道路。
f[x,1]表示以x為根的樹,沒有犯人可以走上來且沒有到出口的道路。
f[x,2]表示以x為根的樹,沒有犯人可以走上來且有到出口的道路。
隨便轉(zhuǎn)移一下即可。
注意葉節(jié)點(diǎn)也犯人點(diǎn)要分類討論一下。
代碼
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std;const int N=100005; const int inf=10000000;int n,m,d[N],f[N][3],last[N],cnt,gui[N]; struct edge{int to,next;}e[N*2];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; }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; }void dfs(int x,int fa) {for (int i=last[x];i;i=e[i].next){if (e[i].to==fa) continue;dfs(e[i].to,x);}if (gui[x]){for (int i=last[x];i;i=e[i].next){if (e[i].to==fa) continue;f[x][0]+=min(f[e[i].to][0],f[e[i].to][1]);}f[x][1]=f[x][2]=inf;}else if (d[x]==1) f[x][0]=f[x][1]=1,f[x][2]=0;else{int s1=0,s2=1;for (int i=last[x];i;i=e[i].next){if (e[i].to==fa) continue;f[x][0]+=min(f[e[i].to][0],f[e[i].to][1]);s1+=f[e[i].to][1];s2+=min(f[e[i].to][0],min(f[e[i].to][1],f[e[i].to][2]));f[x][2]+=min(f[e[i].to][1],f[e[i].to][2]);}f[x][1]=min(s1,s2);f[x][0]=min(f[x][0],s2);f[x][2]=min(f[x][2],s2);} }int main() {n=read()+1;m=read();for (int i=1;i<n;i++){int x=read()+1,y=read()+1;addedge(x,y);d[x]++;d[y]++;}while (m--) {int x=read()+1;gui[x]=1;}for (int i=1;i<=n;i++) if (d[i]==1&&gui[i]) {puts("-1");return 0;}int root=0;for (int i=1;i<=n;i++) if (d[i]>1) {root=i;break;}dfs(root,0);printf("%d",min(f[root][0],min(f[root][1],f[root][2])));return 0; }總結(jié)
以上是生活随笔為你收集整理的51nod 1299 监狱逃离 树形dp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 有趣的囚犯问题
- 下一篇: 51nod-1299 监狱逃离(贪心)