HDU 3491 最小点权割集

Posted L&King

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3491 最小点权割集相关的知识,希望对你有一定的参考价值。

题意:有n个城市,m条双向边,有一群小偷从s前往t偷东西,警察叔叔们想要逮捕小偷们,现在告诉你在每座城市需要多少警察才能抓住这个城市的小偷,为什么说这个城市,因为小偷们会分开跑;然后题目还说不能在s和t逮捕小偷。问需要的最少警力是多少?

分析:这个问题可以变成这样:需要在哪些城市部署警力才能使得小偷不能从s到达t,也即最小点权割集。根据最小割=最大流(此处的最小割是指边权),我们可以这样建图。

建图:把除了s和t的每一个点拆开,在它们之间连一条单向边,权值为该点需要的警力。s和t同样拆开,不过权值为无穷大,因为题目说了不能在s和t逮捕。题目给出的边就按双向边相连,不过起点应该是这个点拆开后的终点,权值为无穷大。最后为了方便,可以把源点和s相连,t和汇点相连,权值都为无穷大。至此,就转换成最小割的模型,求出最大流即可。

手写isap写丑了,没有1A。

 

技术分享
 1 #include<stdio.h>
 2 #include<string.h>
 3 #define min(x,y) (x)<(y)?(x):(y)
 4 const int N=1111,M=1e5+1111,INF=0x3f3f3f3f;
 5 struct node
 6 {
 7     int v,c,next;
 8 }e[M];
 9 int gap[N],h[N],head[N];
10 int s,t,n,m,cnt;
11 void init()
12 {
13     memset(head,-1,sizeof(head));
14     cnt=0;
15 }
16 void add(int u,int v,int w)
17 {
18     e[cnt].v=v,e[cnt].c=w;
19     e[cnt].next=head[u],head[u]=cnt++;
20     e[cnt].v=u,e[cnt].c=0;
21     e[cnt].next=head[v],head[v]=cnt++;
22 }
23 int dfs(int u,int flow)
24 {
25     if(u==t)    return flow;
26     int a,i,v,c=flow,minh=t;
27     for(i=head[u];i!=-1;i=e[i].next)
28     {
29         if(e[i].c)
30         {
31             v=e[i].v;
32             if(h[v]==h[u]-1)
33             {
34                 a=min(c,e[i].c);
35                 a=dfs(v,a);
36                 e[i].c-=a;
37                 e[i^1].c+=a;
38                 c-=a;
39                 if(h[s]>t)    return flow-c;
40                 if(!c)    break;
41             }
42             minh=min(minh,h[v]);
43         }
44     }
45     if(c==flow)
46     {
47         if(--gap[h[u]]==0)    h[s]=t+1;
48         ++gap[h[u]=minh+1];
49     }
50     return flow-c;
51 }
52 int isap()
53 {
54     memset(gap,0,sizeof(gap));
55     memset(h,0,sizeof(h));
56     int ans=0;gap[0]=t+1;
57     while(h[s]<=t)
58         ans+=dfs(s,INF);
59     return ans;
60 }
61 int main()
62 {
63     int T,u,v,i,ss,tt;
64     scanf("%d",&T);
65     while(T--)
66     {
67         scanf("%d%d%d%d",&n,&m,&ss,&tt);
68         init();s=0,t=2*n+1;
69         for(i=1;i<=n;i++)
70         {
71             int x;
72             scanf("%d",&x);
73             if(i!=ss&&i!=tt)
74                 add(i,i+n,x);
75             else
76                 add(i,i+n,INF);
77         }
78         while(m--)
79         {
80             scanf("%d%d",&u,&v);
81             add(u+n,v,INF);
82             add(v+n,u,INF);
83         }
84         add(s,ss,INF);add(tt+n,t,INF);
85         printf("%d\n",isap());
86     }
87     return 0;
88 }
View Code

 

以上是关于HDU 3491 最小点权割集的主要内容,如果未能解决你的问题,请参考以下文章

HDU3491 Thieves(最小割)

HDU 1569 方格取数 << 最大点权独立集

HDU 1569 - 方格取数 - [最大点权独立集与最小点权覆盖集]

hdu 1565&hdu 1569(网络流--最小点权值覆盖)

HDU 1565 - 方格取数 - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

HDU 4859 海岸线(最小割+最大独立点权变形)