監獄有n條道路連線n + 1個交點,編號0至n,整個監獄被這些道路連在一起(任何2點之間都有道路),人們通過道路在交點之間走來走去。其中的一些交點只有一條路連線,這些點是監獄的出口。在各個交點中有m個點住著犯人(m <= n + 1),剩下的點可以安排警衛,有警衛把守的地方犯人無法通過。給出整個監獄的道路情況,以及犯人所在的位置,問至少需要安排多少個警衛,才能保證沒有1個犯人能夠逃到出口,如果總有犯人能夠逃出去,輸出-1。
如上圖所示,點1,6 住著犯人,0,4,5,7,8是出口,至少需要安排4個警衛。
第1行:2個數n, m中間用空格分隔,n表示道路的數量,m表示犯人的數量(1<= n <= 100000, 0 <= m <= n + 1)。之後n行:每行2個數s, e中間用空格分隔,表示點編號為s的點同編號為e的點之間有道路相連。(0 <= s, e <= n)。
之後的m行,每行1個數pi,表示編號為pi的點上有犯人。
輸出1個數對應最少需要多少警衛才能不讓犯人逃出監獄。
8 20 11 2
2 33 4
3 52 6
6 86 7
16
4典型的一道樹形dp,聽說有人跑20萬網路流過了orz
使得任意乙個出口為根節點,逃離方向就固定為向上到根或向下到葉子節點
考慮乙個點的3種狀態:
f[i],表示以i為根的子樹的狀態
f[i]=0,子樹中的點無法到達這個點,且不存在一條從這點到葉子節點的路徑。
f[i]=1,子樹中的點無法到達這個點,但存在一條從這點到葉子節點的路徑。
f[i]=2,子樹中的點可以到達這個點,且不存在一條從這點到葉子節點的路徑
i點的兒子的狀態都為0,則f[i]=0
兒子的狀態有1也有2,則i點必須放,ans++(以為2點可以通過i點到葉子節點)
若i有逃犯則兒子中有1狀態的都要被放,ans加上兒子為1的個數
剩下的兒子狀態單一,直接轉移即可。
1 #include2 #include3 #include4 #include5#define fo(i,a,b) for(int i=a;i<=b;i++)
6#define fd(i,a,b) for(int i=a;i>=b;i--)
7#define fh(i,x) for(int i=head[x];i;i=next[i])
8 typedef long
long
ll;9
using
namespace
std;
10 inline int max(int x,int y)
11 inline int min(int x,int y)
12 inline int
read()
17const
int n=1e5+5;18
intn,m,tot,x,y,ans,d[n],f[n];
19int to[n*2],next[n*2
],head[n];
20bool
bz[n];
21void add(int x,int y)
22void dfs(int x,int
y) 31
intmain()
38 bz[x]=1;39
}40int root=1
;41 fo(i,1,n) if(d[i]==1)
42 dfs(root,0
);43
if(f[root]==2) ans++;
44 printf("
%d\n
",ans);
45 }
51nod 1299 監獄逃離
監獄有n條道路連線n 1個交點,編號0至n,整個監獄被這些道路連在一起 任何2點之間都有道路 人們通過道路在交點之間走來走去。其中的一些交點只有一條路連線,這些點是監獄的出口。在各個交點中有m個點住著犯人 m n 1 剩下的點可以安排警衛,有警衛把守的地方犯人無法通過。給出整個監獄的道路情況,以及犯...
51Nod 1299 監獄逃離
這其實是一道樹形dp的神仙題。然後開始推推推,1 hour later樣例都過不了 然後仔細一看題目,貌似像乙個最小割模型,然後5min想了想建圖 首先拆點,將每個點拆成進和出兩個,然後連邊,邊權即為 1 表示割掉這條邊的代價 然後設超級源 s 讓 s 向所有犯人的出點 因為犯人的點無法割去 連邊,...
51nod 1299 監獄逃離
1299 監獄逃離 基準時間限制 1 秒 空間限制 131072 kb 監獄有n條道路連線n 1個交點,編號0至n,整個監獄被這些道路連在一起 任何2點之間都有道路 人們通過道路在交點之間走來走去。其中的一些交點只有一條路連線,這些點是監獄的出口。在各個交點中有m個點住著犯人 m n 1 剩下的點可...