[51nod1299]监狱逃离 树形DP || 20w个点的网络流最小割ORZ
監(jiān)獄有N條道路連接N + 1個(gè)交點(diǎn),編號(hào)0至N,整個(gè)監(jiān)獄被這些道路連在一起(任何2點(diǎn)之間都有道路),人們通過(guò)道路在交點(diǎn)之間走來(lái)走去。其中的一些交點(diǎn)只有一條路連接,這些點(diǎn)是監(jiān)獄的出口。在各個(gè)交點(diǎn)中有M個(gè)點(diǎn)住著犯人(M <= N + 1),剩下的點(diǎn)可以安排警衛(wèi),有警衛(wèi)把守的地方犯人無(wú)法通過(guò)。給出整個(gè)監(jiān)獄的道路情況,以及犯人所在的位置,問(wèn)至少需要安排多少個(gè)警衛(wèi),才能保證沒(méi)有1個(gè)犯人能夠逃到出口,如果總有犯人能夠逃出去,輸出-1。
如上圖所示,點(diǎn)1,6 住著犯人,0,4,5,7,8是出口,至少需要安排4個(gè)警衛(wèi)。
Input
第1行:2個(gè)數(shù)N, M中間用空格分隔,N表示道路的數(shù)量,M表示犯人的數(shù)量(1<= N <= 100000, 0 <= M <= N + 1)。
之后N行:每行2個(gè)數(shù)S, E中間用空格分隔,表示點(diǎn)編號(hào)為S的點(diǎn)同編號(hào)為E的點(diǎn)之間有道路相連。(0 <= S, E <= N)。
之后的M行,每行1個(gè)數(shù)Pi,表示編號(hào)為Pi的點(diǎn)上有犯人。
Output
輸出1個(gè)數(shù)對(duì)應(yīng)最少需要多少警衛(wèi)才能不讓犯人逃出監(jiān)獄。
Input示例
8 2
0 1
1 2
2 3
3 4
3 5
2 6
6 8
6 7
1
6
Output示例
4
ORZ ,學(xué)長(zhǎng)在網(wǎng)絡(luò)流專(zhuān)題里放這么一道毒瘤題,20w個(gè)點(diǎn),他說(shuō)可以用網(wǎng)絡(luò)流遛一遛。。。。 我自己寫(xiě)的網(wǎng)絡(luò)流交了十多發(fā)才卡過(guò)去。。。。
ヽ(ー_ー)ノ
正解應(yīng)該是樹(shù)形DP,那時(shí)候并不了解樹(shù)形DP。。 看題解都理解了好久。。。。。
這道題跟UVA1218的狀態(tài)轉(zhuǎn)移方程有一些相似。有興趣的可以去看一哈。 也挺有意思的
**
解題思路
**
他給出的是一棵樹(shù),求的是最小花費(fèi)問(wèn)題,圖上的最小花費(fèi)一般是最短路,網(wǎng)絡(luò)流,或者DP問(wèn)題了。 這里由于20w個(gè)點(diǎn),網(wǎng)絡(luò)流應(yīng)該首先被pass掉(實(shí)在不行也可以試一發(fā),暴力出奇跡)。
這題看不出跟最短路有啥關(guān)系,我們應(yīng)該往樹(shù)形DP的方向去想。
我們來(lái)考慮一下,放完警衛(wèi)后,這個(gè)樹(shù)形圖上每個(gè)點(diǎn)的狀態(tài)會(huì)是怎么樣的。
狀態(tài)一. 這個(gè)點(diǎn)的子樹(shù)上的逃犯逃不到這個(gè)點(diǎn),這個(gè)點(diǎn)也無(wú)法通向的它子樹(shù)的葉子節(jié)點(diǎn)
狀態(tài)二. 這個(gè)點(diǎn)的子樹(shù)上的逃犯逃不到這個(gè)點(diǎn),這個(gè)點(diǎn)有通向其葉子節(jié)點(diǎn)的路徑
狀態(tài)三. 這個(gè)點(diǎn)的子樹(shù)上的逃犯能到達(dá)這個(gè)節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)無(wú)法通向其子樹(shù)的葉子節(jié)點(diǎn)。
除此之外,如果這個(gè)圖擁有其他狀態(tài)的點(diǎn),那么絕對(duì)不合法。
這里在我們更新子節(jié)點(diǎn)的時(shí)候不用考慮這個(gè)節(jié)點(diǎn)父親節(jié)點(diǎn)的狀況,因?yàn)楦赣H節(jié)點(diǎn)的狀態(tài)就是由子節(jié)點(diǎn)唯一確定的。
狀態(tài)很少,所以我們可以很輕易的枚舉所有狀態(tài)。 由此可以寫(xiě)出dp數(shù)組的定義
怎么轉(zhuǎn)移呢。 分類(lèi)討論一下,判斷出每種狀態(tài)的優(yōu)先級(jí)不停if else即可。。。。。。。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> #include<cmath> #include<limits> #include<map> #include<set> #include<stack> #include<string> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fuck(x) cout<<"["<<x<<"]"<<endl #define mem(a,b) memset(a,b,sizeof a); class edges { public:int u,v,next; }; edges edge[100005*2]; int tot=0; int head[100005]; int ans=0; void init() {mem(head,-1);tot=0;ans=0; } void add(int u,int v) {edge[tot].u=u; edge[tot].v=v;edge[tot].next=head[u];head[u]=tot; tot++; } int people[100005]; int dp[100005]; // 0表示子節(jié)點(diǎn)的逃犯無(wú)法到達(dá)這個(gè)節(jié)點(diǎn),該節(jié)點(diǎn)可通向葉子結(jié)點(diǎn)。 既葉子節(jié)點(diǎn)的初始狀態(tài) // 1表示 表示子節(jié)點(diǎn)逃犯無(wú)法到達(dá)這個(gè)節(jié)點(diǎn),該節(jié)點(diǎn)不可通向葉子結(jié)點(diǎn) // 2表示該節(jié)點(diǎn)的子樹(shù)的有逃犯可以到達(dá)該節(jié)點(diǎn),且該節(jié)點(diǎn)不可以通向葉子節(jié)點(diǎn) 囚犯所在的節(jié)點(diǎn)都會(huì)是這個(gè)狀態(tài) void dfs(int root,int per) {int s[3]={0,0,0};for(int i=head[root];i!=-1;i=edge[i].next){int v=edge[i].v;if(v==per)continue;dfs(v,root);s[dp[v]]++;}if(people[root]){dp[root]=2;ans+=s[0];}else if(s[2]&&s[0]){ans++;dp[root]=1;}else if(s[0]){dp[root]=0;}else if(s[2]){dp[root]=2;}else if(s[1]){dp[root]=1;} } int du[100005]; int main() {int n,m;scanf("%d %d",&n,&m);init();for(int i=1;i<=n;i++){int u,v;scanf("%d %d",&u,&v);add(u,v);add(v,u);du[u]++;du[v]++;}for(int i=1;i<=m;i++){int root;scanf("%d",&root);people[root]=1;}for(int i=1;i<n;i++){if(du[i]==1){dfs(i,-1);if(dp[i]==2)ans++;cout<<ans<<endl;break;}}return 0; }總結(jié)
以上是生活随笔為你收集整理的[51nod1299]监狱逃离 树形DP || 20w个点的网络流最小割ORZ的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 云南毒贩越狱出逃 监狱安防漏洞都在哪儿?
- 下一篇: 【排序】一次查找两元素