日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[51nod1299]监狱逃离

發(fā)布時間:2023/12/8 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [51nod1299]监狱逃离 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Description

給出一個n+1個點(diǎn)n條邊的樹,其中每一個度數(shù)為1的點(diǎn)為出口。
現(xiàn)在有一些點(diǎn)有逃犯,你需要在一些沒有逃犯的點(diǎn)放置警衛(wèi),有警衛(wèi)的點(diǎn)逃犯無法經(jīng)過。
求若使所有逃犯均無法到達(dá)出口,最少需要多少個警衛(wèi)。
n<=10^5

Solution

為什么我一眼想到最小割=w=
就是所有的逃犯無法到達(dá)一些點(diǎn),那么我們把每個點(diǎn)拆點(diǎn),x向x’連容量為1的邊,割掉這條邊表示在這個點(diǎn)放置警衛(wèi)。
然后對于原圖中的每一條邊(x,y),從x’向y連容量為∞的邊,表示這條邊無法被割掉。
同理從S向每個有逃犯的x’點(diǎn)連容量為∞的邊,因?yàn)闊o法在有逃犯的點(diǎn)放置警衛(wèi)。
然后從每個出口的x’點(diǎn)向T連容量為∞的邊,因?yàn)榭梢栽诔隹诜胖镁l(wèi)。
然后跑一邊最小割就是答案了。如果最小割為∞就是無解。
200000個點(diǎn)的最大流什么的真是夢想_ (:зゝ∠)_
然而它碾過去了2333

好吧我們來討論正解=w=
隨便選一個度數(shù)為1的點(diǎn)做根節(jié)點(diǎn),那么所有的出口都是根節(jié)點(diǎn)或者葉子節(jié)點(diǎn)了。
考慮從下往上遞推,每個點(diǎn)可以有三種情況
0:這個點(diǎn)為根的子樹中所有的逃犯都無法到達(dá)這個點(diǎn),且不存在一條從這點(diǎn)到葉子節(jié)點(diǎn)的路徑。
1:這個點(diǎn)為根的子樹中所有的逃犯都無法到達(dá)這個點(diǎn),但存在一條從這點(diǎn)到葉子節(jié)點(diǎn)的路徑。
2:這個點(diǎn)為根的子樹中所有的逃犯有可能到達(dá)這個點(diǎn),且不存在一條從這點(diǎn)到葉子節(jié)點(diǎn)的路徑。
那么考慮一個點(diǎn),如果它的所有兒子都被封死了(就是狀態(tài)0),那么它自己也就被封死了。
如果這個點(diǎn)有逃犯,那么這個點(diǎn)一下的1點(diǎn)都必須被封死,要不然逃犯可以通過這個點(diǎn)到葉子節(jié)點(diǎn),所以答案加上當(dāng)前節(jié)點(diǎn)狀態(tài)為1的兒子個數(shù)。
否則如果當(dāng)前點(diǎn)既有狀態(tài)為1的兒子,又有狀態(tài)為2的兒子,那么2的逃犯就可以到達(dá)這個點(diǎn),然后從這個點(diǎn)往下逃走。
所以這個點(diǎn)必須被封死。
否則就是只有0\1,0\2的情況,那么除0外是幾這個點(diǎn)的狀態(tài)就是幾。
最后如果根節(jié)點(diǎn)的狀態(tài)為2根節(jié)點(diǎn)也要封死。

Code

最小割

#include <cstdio> #include <cstring> #include <algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define rep(i,a) for(int i=last[a];i;i=next[i]) using namespace std; const int N=2*1e5+5,inf=1e5; int n,m,S,T,l,x,y,ans,dis[N],d[N],r[N]; int t[N*8],next[N*8],f[N*8],last[N]; void add(int x,int y,int z) {t[++l]=y;f[l]=z;next[l]=last[x];last[x]=l;t[++l]=x;f[l]=0;next[l]=last[y];last[y]=l; } bool bfs() {memset(dis,0,sizeof(dis));dis[S]=1;int i=0,j=1;d[1]=S;while (i<j) rep(k,d[++i]) if (!dis[t[k]]&&f[k]) dis[t[k]]=dis[d[i]]+1,d[++j]=t[k];return dis[T]; } int dinic(int x,int y) {if (x==T) return y;int now=0;rep(i,x) if (f[i]&&dis[t[i]]==dis[x]+1) {int k=dinic(t[i],min(y,f[i]));y-=k;now+=k;f[i]-=k;f[i^1]+=k;if (!y) break;}if (!now) dis[x]=-1;return now; } int main() {scanf("%d%d",&n,&m);n++;S=0;T=2*n+1;l=1;fo(i,1,n-1) {scanf("%d%d",&x,&y);x++;y++;add(x+n,y,inf);add(y+n,x,inf);r[x]++;r[y]++;}fo(i,1,m) scanf("%d",&x),x++,add(S,x+n,inf);fo(i,1,n) if (r[i]==1) add(i+n,T,inf);fo(i,1,n) add(i,i+n,1);while (bfs()) ans+=dinic(S,inf);if (ans>=inf) printf("-1\n");else printf("%d\n",ans); }

Dp

#include <cstdio> #include <cstring> #include <algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define rep(i,a) for(int i=last[a];i;i=next[i]) using namespace std; const int N=1e5+5; int n,m,l,x,y,ans,d[N],f[N]; int t[N*2],next[N*2],last[N]; bool bz[N]; void add(int x,int y) {t[++l]=y;next[l]=last[x];last[x]=l; } void dfs(int x,int y) {int s[3];memset(s,0,sizeof(s));rep(i,x) if (t[i]!=y) {dfs(t[i],x);s[f[t[i]]]++;}if (bz[x]) {ans+=s[1];f[x]=2;} else if (s[1]&&s[2]) {ans++;f[x]=0;} else if (s[1]) f[x]=1;else if (s[2]) f[x]=2;else if (s[0]) f[x]=0; } int main() {scanf("%d%d",&n,&m);n++;fo(i,1,n-1) {scanf("%d%d",&x,&y),x++,y++;add(x,y),add(y,x);d[x]++;d[y]++;}fo(i,1,n) f[i]=1;fo(i,1,m) {scanf("%d",&x),x++;if (d[x]==1) {printf("-1\n");return 0;}bz[x]=1;}fo(i,1,n) if (d[i]==1) {dfs(i,0);if (f[i]==2) ans++;break;}printf("%d\n",ans); }

總結(jié)

以上是生活随笔為你收集整理的[51nod1299]监狱逃离的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。