HDU 3987 && DINIC

很容易发现是网络流的题目,但最少边怎么求呢?初时想不到,但画图后忽然发现可以这样:

求一次网络流最小割后,把满流的边置1,不满流的置INF。再求一次最大流即可。

为什么呢?

是否会存在一些边当前不满流,但有可能是最少边数最少割的边呢?否。因为按照DINIC的求法,每次都是增广容量最少的路,若当前不满流,则必定不是最小割的边,所以只需在满流的边,即可组成最小割的边寻找最少边就可以了。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 using namespace std;
  6
  7 const int INF=0x3f3f3f3f;
  8 const int MAXN=1050;
  9 const int MAXM=400000;
 10
 11 struct Node{
 12     int from,to,next;
 13     int cap;
 14 }edge[MAXM];
 15 int tol;
 16
 17 int dep[MAXN];
 18 int head[MAXN];
 19
 20 int n,m;
 21 void init(){
 22     tol=0;
 23     memset(head,-1,sizeof(head));
 24 }
 25 void addedge(int u,int v,int w){
 26     edge[tol].from=u;
 27     edge[tol].to=v; edge[tol].cap=w;  edge[tol].next=head[u];
 28     head[u]=tol++;
 29     edge[tol].from=v;
 30     edge[tol].to=u;
 31     edge[tol].cap=0;
 32     edge[tol].next=head[v];
 33     head[v]=tol++;
 34 }
 35
 36 int BFS(int start,int end){
 37     int que[MAXN];
 38     int front,rear; front=rear=0;
 39     memset(dep,-1,sizeof(dep));
 40     que[rear++]=start;
 41     dep[start]=0;
 42     while(front!=rear)    {
 43         int u=que[front++];
 44         if(front==MAXN)front=0;
 45         for(int i= head[u];i!=-1; i=edge[i].next){
 46             int v=edge[i].to;
 47             if(edge[i].cap>0&& dep[v]==-1){
 48                 dep[v]=dep[u]+1;
 49                 que[rear++]=v;
 50                 if(rear>=MAXN) rear=0;
 51                 if(v==end)return 1;
 52             }
 53         }
 54     }
 55     return 0;
 56 }
 57 int dinic(int start,int end){
 58     int res=0;
 59     int top;
 60     int stack[MAXN];
 61     int cur[MAXN];
 62     while(BFS(start,end)){
 63         memcpy(cur,head, sizeof(head));
 64         int u=start;
 65         top=0;
 66         while(1){
 67             if(u==end){
 68                 int min=INF;
 69                 int loc;
 70                for(int i=0;i<top;i++)
 71                   if(min>edge [stack[i]].cap) {
 72                       min=edge [stack[i]].cap;
 73                       loc=i;
 74                   }
 75                 for(int i=0;i<top;i++){
 76                     edge[stack[i]].cap-=min;
 77                     edge[stack[i]^1].cap+=min;
 78                 }
 79                 res+=min;
 80                 top=loc;
 81                 u=edge[stack[top]].from;
 82             }
 83             for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next)
 84               if(edge[i].cap!=0 && dep[u]+1==dep[edge[i].to])
 85                  break;
 86             if(cur[u] !=-1){
 87                 stack [top++]= cur[u];
 88                 u=edge[cur[u]].to;
 89             }
 90             else{
 91                 if(top==0) break;
 92                 dep[u]=-1;
 93                 u= edge[stack [--top] ].from;
 94             }
 95         }
 96     }
 97     return res;
 98 }
 99
100 int main(){
101     int T,cas=0;
102     int u,v,w,d;
103     scanf("%d",&T);
104     while(T--){
105         init();
106         cas++;
107         scanf("%d%d",&n,&m);
108         for(int i=0;i<m;i++){
109             scanf("%d%d%d%d",&u,&v,&w,&d);
110             if(d){
111                 addedge(v,u,w);
112             }
113             addedge(u,v,w);
114         }
115         dinic(0,n-1);
116         for(int i=0;i<tol;i+=2){
117             if(edge[i].cap==0){
118                 edge[i].cap=1; edge[i^1].cap=0;
119             }
120             else {
121                 edge[i].cap=INF;
122                 edge[i^1].cap=0;
123             }
124         }
125         int ans=dinic(0,n-1);
126         printf("Case %d: ",cas);
127         printf("%d\n",ans);
128     }
129     return 0;
130 }

DINIC的模板

 1 const int INF=0x3f3f3f3f;
 2 const int MAXN=1050;
 3 const int MAXM=400000;
 4
 5 struct Node{
 6     int from,to,next;
 7     int cap;
 8 }edge[MAXM];
 9 int tol;
10
11 int dep[MAXN];
12 int head[MAXN];
13
14 int n,m;
15 void init(){
16     tol=0;
17     memset(head,-1,sizeof(head));
18 }
19 void addedge(int u,int v,int w){
20     edge[tol].from=u;
21     edge[tol].to=v; edge[tol].cap=w;  edge[tol].next=head[u];
22     head[u]=tol++;
23     edge[tol].from=v;
24     edge[tol].to=u;
25     edge[tol].cap=0;
26     edge[tol].next=head[v];
27     head[v]=tol++;
28 }
29
30 int BFS(int start,int end){
31     int que[MAXN];
32     int front,rear; front=rear=0;
33     memset(dep,-1,sizeof(dep));
34     que[rear++]=start;
35     dep[start]=0;
36     while(front!=rear)    {
37         int u=que[front++];
38         if(front==MAXN)front=0;
39         for(int i= head[u];i!=-1; i=edge[i].next){
40             int v=edge[i].to;
41             if(edge[i].cap>0&& dep[v]==-1){
42                 dep[v]=dep[u]+1;
43                 que[rear++]=v;
44                 if(rear>=MAXN) rear=0;
45                 if(v==end)return 1;
46             }
47         }
48     }
49     return 0;
50 }
51 int dinic(int start,int end){
52     int res=0;
53     int top;
54     int stack[MAXN];
55     int cur[MAXN];
56     while(BFS(start,end)){
57         memcpy(cur,head, sizeof(head));
58         int u=start;
59         top=0;
60         while(1){
61             if(u==end){
62                 int min=INF;
63                 int loc;
64                for(int i=0;i<top;i++)
65                   if(min>edge [stack[i]].cap) {
66                       min=edge [stack[i]].cap;
67                       loc=i;
68                   }
69                 for(int i=0;i<top;i++){
70                     edge[stack[i]].cap-=min;
71                     edge[stack[i]^1].cap+=min;
72                 }
73                 res+=min;
74                 top=loc;
75                 u=edge[stack[top]].from;
76             }
77             for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next)
78               if(edge[i].cap!=0 && dep[u]+1==dep[edge[i].to])
79                  break;
80             if(cur[u] !=-1){
81                 stack [top++]= cur[u];
82                 u=edge[cur[u]].to;
83             }
84             else{
85                 if(top==0) break;
86                 dep[u]=-1;
87                 u= edge[stack [--top] ].from;
88             }
89         }
90     }
91     return res;
92 }

HDU 3987 && DINIC

时间: 2024-11-06 07:30:49

HDU 3987 && DINIC的相关文章

hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割

view code//hdu 3987 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; typedef long long ll; const ll INF = 1LL<<59; const ll E = 100001; const int N = 10

HDU 3572 Dinic

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4323    Accepted Submission(s): 1447 Problem Description Our geometry princess XMM has stoped her study in computational geometry to

hdu 3987 求最小割条数最小

题意:    一个人要从起点  0  到达 n-1   n个点  m条路  ,我们求最少破坏路的条数使无法 从起点到达终点.题意很明显  ,求最小割条数最少,由于最小割流量虽然固定,但是其条数却不固定,可以破坏3条路,也可以破坏4条路,他们总流量相同才会出现这种情况. 题解:由于上述的情况,他们总流量相同但是条数不同,现在我们需要改变边的容量使得条数少边才是最小割,条数多的将不会是最小割. 官方题解有两种 ,我选择的是在残余网络中进行扩充流的操作,使的两个最小割不同,残余网络中,我进行所有边流量

hdu 3987 Harry Potter and the Forbidden Forest【网路流最小割模型】

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1549    Accepted Submission(s): 528 Problem Description Harry Potter notices some Death Eaters try to slip

【网络流#3】hdu 1532 - Dinic模板题

输入为m,n表示m条边,n个结点 记下来m行,每行三个数,x,y,c表示x到y的边流量最大为c 这道题的模板来自于网络 http://blog.csdn.net/sprintfwater/article/details/7913061 建议大家去这个页面看看,博主也很良心地添加了很多注释 关于这个模板:Edge为前向星的边数,所以需要初始化Edge和head数组 n表示有n个点,这个版无所谓点从0开始还是从1开始,s表示源点,t表示汇点很好的一个是,这个版的DFS使用的是模拟栈,防止爆栈 1 #

HDU 3987 Harry Potter and the Forbidden Forest(最小割中的最少割边)经典

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1791    Accepted Submission(s): 596 Problem Description Harry Potter notices some Death Eaters try to slip

HDU 3549 Dinic

Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 8946    Accepted Submission(s): 4205 Problem Description Network flow is a well-known difficult problem for ACMers. Given a graph, yo

HDU 1532 Dinic

Drainage Ditches Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10242    Accepted Submission(s): 4867 Problem Description Every time it rains on Farmer John's fields, a pond forms over Bessie's

HDU - 2732 Leapin&#39; Lizards(ISAP Dinic EK)

题目大意:给出两张地图,第一章地图代表的是每根柱子的高度,第二张地图代表的是每只蜥蜴所在的位置 每根柱子只能站一只蜥蜴,蜥蜴离开该柱子时,柱子的高度会下降一个单元,当柱子的高度为0时,该柱子将不可用 现在给出每只蜥蜴能跳跃的距离,问最少有多少只蜥蜴逃不出来 解题思路:将柱子拆成2个点,权值为柱子的高度 将每只蜥蜴所在的位置和超级源点连接,权值为1 将能通到外界的柱子连接到超级汇点,权值为INF 如果柱子间的距离满足蜥蜴跳跃的距离,连接起来,权值为INF 这样图就完成了 ISAP: #includ