What is the minimum cut problem in the game URAL1277 Cops and Thieves?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1047个文字,预计阅读时间需要5分钟。
《警察与盗贼描述:银河警察(Galaxpol)发现一个臭名昭著的盗贼团伙计划从地球行星博物馆偷走一件极为珍贵的展品——一台古老的微处理器。警察局长决定...》
Cops and Thieves
Description:
10 5 5 1 5 1 6 6 11 1 1 2 1 3 2 4 3 4 4 5 Sample Output:
NO 题意: 给出一个无向图以及其起点和终点,每个点都有点权,问是否能用k个人去截断起点到终点的路径,注意不能将人员安排在起点和终点上面。 题解: 就是一个最小割的问题,建双向边以及拆点就好了。因为不能在起点和终点安排人员,所以起点和终点拆边的时候容量为无穷大就行了。 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #define INF 1e9 using namespace std; typedef long long ll; const int N = 505,M = 1e5+5; int n,m,s,F,tot,k; int w[N],head[N],d[N]; struct Edge{ int u,v,c,next; }e[M]; void adde(int u,int v,int c){ e[tot].v=v;e[tot].next=head[u];e[tot].c=c;head[u]=tot++; e[tot].v=u;e[tot].next=head[v];e[tot].c=0;head[v]=tot++; } int bfs(){ memset(d,0,sizeof(d));d[F]=1; queue <int > q;q.push(F); while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(e[i].c>0 && !d[v]){ d[v]=d[u]+1; q.push(v); } } } return d[s+n]!=0; } int dfs(int S,int a){ if(S==s+n || a==0) return a; int flow=0,f; for(int i=head[S];i!=-1;i=e[i].next){ int v=e[i].v; if(d[v]!=d[S]+1) continue ; f=dfs(v,min(a,e[i].c)); if(f>0){ e[i].c-=f; e[i^1].c+=f; flow+=f; a-=f; if(a==0) break; } } if(!flow) d[S]=-1; return flow; } int Dinic(int S,int T){ int flow = 0; while(bfs()) flow+=dfs(S,INF); return flow ; } int main(){ cin>>k>>n>>m>>s>>F; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=n;i++){ if(i==s ||i==F) adde(i,i+n,INF); else adde(i,i+n,w[i]); } for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); adde(u+n,v,INF);adde(v+n,u,INF); } int flow = Dinic(F,s+n); if(flow>k) cout<<"NO"; else cout<<"YES"; return 0; }
本文共计1047个文字,预计阅读时间需要5分钟。
《警察与盗贼描述:银河警察(Galaxpol)发现一个臭名昭著的盗贼团伙计划从地球行星博物馆偷走一件极为珍贵的展品——一台古老的微处理器。警察局长决定...》
Cops and Thieves
Description:
10 5 5 1 5 1 6 6 11 1 1 2 1 3 2 4 3 4 4 5 Sample Output:
NO 题意: 给出一个无向图以及其起点和终点,每个点都有点权,问是否能用k个人去截断起点到终点的路径,注意不能将人员安排在起点和终点上面。 题解: 就是一个最小割的问题,建双向边以及拆点就好了。因为不能在起点和终点安排人员,所以起点和终点拆边的时候容量为无穷大就行了。 代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> #define INF 1e9 using namespace std; typedef long long ll; const int N = 505,M = 1e5+5; int n,m,s,F,tot,k; int w[N],head[N],d[N]; struct Edge{ int u,v,c,next; }e[M]; void adde(int u,int v,int c){ e[tot].v=v;e[tot].next=head[u];e[tot].c=c;head[u]=tot++; e[tot].v=u;e[tot].next=head[v];e[tot].c=0;head[v]=tot++; } int bfs(){ memset(d,0,sizeof(d));d[F]=1; queue <int > q;q.push(F); while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(e[i].c>0 && !d[v]){ d[v]=d[u]+1; q.push(v); } } } return d[s+n]!=0; } int dfs(int S,int a){ if(S==s+n || a==0) return a; int flow=0,f; for(int i=head[S];i!=-1;i=e[i].next){ int v=e[i].v; if(d[v]!=d[S]+1) continue ; f=dfs(v,min(a,e[i].c)); if(f>0){ e[i].c-=f; e[i^1].c+=f; flow+=f; a-=f; if(a==0) break; } } if(!flow) d[S]=-1; return flow; } int Dinic(int S,int T){ int flow = 0; while(bfs()) flow+=dfs(S,INF); return flow ; } int main(){ cin>>k>>n>>m>>s>>F; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<=n;i++){ if(i==s ||i==F) adde(i,i+n,INF); else adde(i,i+n,w[i]); } for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); adde(u+n,v,INF);adde(v+n,u,INF); } int flow = Dinic(F,s+n); if(flow>k) cout<<"NO"; else cout<<"YES"; return 0; }

