网络流 KM dinic

 

study from:

https://blog.csdn.net/A_Comme_Amour/article/details/79356220

 

1.

Edmonds-Karp 无优化

最坏时间复杂度O(n*m*m) n为点数,m为边数

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <ctime>
  5 #include <cstring>
  6 #include <string>
  7 #include <map>
  8 #include <set>
  9 #include <list>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <bitset>
 14 #include <algorithm>
 15 #include <iostream>
 16 using namespace std;
 17 #define ll long long
 18 const int maxn=1e4+10;
 19 const int inf=1e9;
 20 
 21 struct node
 22 {
 23     int d,len;
 24     node *next,*opp;
 25 }*e[maxn],*pre[maxn];
 26 
 27 int sum=0,s,t,add[maxn];
 28 queue<int> st;
 29 bool vis[maxn];
 30 
 31 void add_edge(int x,int y,int len)
 32 {
 33     node *p1=(node*) malloc (sizeof(node));
 34     node *p2=(node*) malloc (sizeof(node));
 35 
 36     p1->d=y;
 37     p1->len=len;
 38     p1->next=e[x];
 39     p1->opp=p2;
 40     e[x]=p1;
 41 
 42     p2->d=x;///注意
 43     p2->len=0;///注意
 44     p2->next=e[y];
 45     p2->opp=p1;
 46     e[y]=p2;
 47 }
 48 
 49 void bfs()
 50 {
 51     int d,dd,v;
 52     node *p;
 53     while (1)
 54     {
 55         memset(add,0,sizeof(add));
 56         ///vis不用初始化
 57         add[s]=inf;
 58         vis[s]=1;
 59         st.push(s);
 60         while (!st.empty())
 61         {
 62             d=st.front();
 63             st.pop();
 64             p=e[d];
 65             while (p)
 66             {
 67                 dd=p->d;
 68                 v=min(add[d],p->len);
 69                 if (add[dd]<v)
 70                 {
 71                     add[dd]=v;
 72                     pre[dd]=p->opp;
 73                     if (!vis[dd])
 74                     {
 75                         vis[dd]=1;
 76                         st.push(dd);
 77                     }
 78                 }
 79                 p=p->next;
 80             }
 81             vis[d]=0;
 82         }
 83 
 84         if (add[t]==0)
 85             break;
 86 
 87         sum+=add[t];
 88         d=t;
 89         while (d!=s)
 90         {
 91             pre[d]->len+=add[t];
 92             pre[d]->opp->len-=add[t];
 93             d=pre[d]->d;
 94         }
 95     }
 96 }
 97 
 98 int main()
 99 {
100     int n,m,x,y,z;
101     scanf("%d%d%d%d",&n,&m,&s,&t);
102     while (m--)
103     {
104         scanf("%d%d%d",&x,&y,&z);
105         add_edge(x,y,z);
106     }
107     bfs();
108     printf("%d",sum);
109     return 0;
110 }

 

2.

study from https://www.luogu.org/problemnew/solution/P3376 第一个题解的dinic

dinic

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cmath>
  4 #include <ctime>
  5 #include <cstring>
  6 #include <string>
  7 #include <map>
  8 #include <set>
  9 #include <list>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <bitset>
 14 #include <algorithm>
 15 #include <iostream>
 16 using namespace std;
 17 #define ll long long
 18 const int maxn=1e4+10;
 19 const int inf=1e9;
 20 
 21 struct node
 22 {
 23     int d,len;
 24     node *next,*opp;
 25 }*e[maxn];
 26 
 27 int sum=0,s,t;
 28 int q[maxn],dep[maxn];
 29 bool vis[maxn];
 30 
 31 void add_edge(int x,int y,int len)
 32 {
 33     node *p1=(node*) malloc (sizeof(node));
 34     node *p2=(node*) malloc (sizeof(node));
 35 
 36     p1->d=y;
 37     p1->len=len;
 38     p1->next=e[x];
 39     p1->opp=p2;
 40     e[x]=p1;
 41 
 42     p2->d=x;
 43     p2->len=0;///注意
 44     p2->next=e[y];
 45     p2->opp=p1;
 46     e[y]=p2;
 47 }
 48 
 49 ///前面的网络流算法,每进行一次增广,都要做 一遍BFS,十分浪费。能否少做几次BFS?
 50 
 51 bool bfs()
 52 {
 53     int head=0,tail=1,d,dd;
 54     node *p;
 55     memset(vis,0,sizeof(vis));
 56     vis[s]=1;
 57     dep[s]=1;
 58     q[1]=s;
 59 
 60     while (head<tail)
 61     {
 62         head++;
 63         d=q[head];
 64         p=e[d];
 65         while (p)
 66         {
 67             dd=p->d;
 68             if (p->len>0 && !vis[dd])
 69             {
 70                 tail++;
 71                 q[tail]=dd;
 72                 vis[dd]=1;
 73                 dep[dd]=dep[d]+1;
 74             }
 75             p=p->next;
 76         }
 77     }
 78     if (vis[t])
 79         return 1;
 80     return 0;
 81 }
 82 
 83 ///DFS找到一条增广路径后,并不立即结束,而是回溯后继续DFS寻找下一个增广路径
 84 
 85 int dfs(int d,int add)
 86 {
 87     if (!add || d==t)
 88         return add;
 89     int totf=0,f,dd;
 90     node *p=e[d];
 91     while (p)
 92     {
 93         dd=p->d;
 94         if (dep[dd]==dep[d]+1 && (f=dfs(dd,min(add,p->len)))>0)///注意
 95         {
 96             totf+=f;
 97             add-=f;///注意
 98             p->len-=f;
 99             p->opp->len+=f;
100         }
101         p=p->next;
102     }
103     return totf;
104 }
105 
106 int main()
107 {
108     int n,m,x,y,z;
109     scanf("%d%d%d%d",&n,&m,&s,&t);
110     while (m--)
111     {
112         scanf("%d%d%d",&x,&y,&z);
113         add_edge(x,y,z);
114     }
115     while (bfs())
116         sum+=dfs(s,inf);
117     printf("%d",sum);
118     return 0;
119 }

 

posted @ 2018-09-01 10:00  congmingyige  阅读(282)  评论(0编辑  收藏  举报