【dinic求最大权闭合子图】课程开发计划

首先get知识点讲解(活动和邀请学生的题,主要看如何建图的和结论!很重要!):

https://blog.csdn.net/Cold_Chair/article/details/52841351

结论:最大权闭合子图 = 正点和-最小割。(同时,如果题目要求不仅要是最大权,并且要求"活动"点数还最少,那代码不用变,照样满足。

这种题型都是直接套这个结论即可。




大致思路

就是用结论“正点和-最小割=最大权闭合子图”

建图如下:


代码

[cpp]  view plain  copy
  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<algorithm>  
  4. #include<queue>  
  5. #define maxn 5010  
  6. #define maxm 50100  
  7. #define inf 0x3f3f3f3f  
  8. using namespace std;  
  9. struct Edge{  
  10.     int v,c,next;  
  11.     Edge(int v,int c,int next):v(v),c(c),next(next){}  
  12.     Edge(){}  
  13. }e[maxm*6+maxn*2];  
  14. int p[maxn+maxm];  
  15. int cnt,n,m,T;  
  16. void init(){  
  17.     cnt=0;  
  18.     memset(p,-1,sizeof(p));  
  19. }  
  20. void insert(int u,int v,int c){  
  21.     e[cnt]=Edge(v,c,p[u]);  
  22.     p[u]=cnt++;  
  23. }  
  24. int d[maxn+maxm];  
  25. bool bfs(){  
  26.     memset(d,-1,sizeof(d));  
  27.     queue<int>q;  
  28.     d[0]=0;  
  29.     q.push(0);  
  30.     while(!q.empty()){  
  31.         int u=q.front();q.pop();  
  32.         for(int i=p[u];i!=-1;i=e[i].next){  
  33.             int v=e[i].v;  
  34.             if(e[i].c>0&&d[v]==-1){  
  35.                 //printf("%d->%d(%d)\n",u,v,d[u]+1);  
  36.                 d[v]=d[u]+1;  
  37.                 q.push(v);  
  38.             }  
  39.         }  
  40.     }  
  41.     return d[T]!=-1;  
  42. }  
  43. int dfs(int u,int flow){  
  44.     if(u==T)return flow;  
  45.     int res=0;  
  46.     for(int i=p[u];i!=-1;i=e[i].next){  
  47.         int v=e[i].v;  
  48.         if(e[i].c>0&&d[v]==d[u]+1){  
  49.             int tmp=dfs(v,min(flow,e[i].c));  
  50.             e[i].c-=tmp;  
  51.             flow-=tmp;  
  52.             e[i^1].c+=tmp;  
  53.             res+=tmp;  
  54.             if(flow==0)  
  55.                 break;  
  56.         }  
  57.     }  
  58.     if(res==0)  
  59.         d[u]=-1;  
  60.     return res;  
  61. }  
  62. int dinic(){  
  63.     int res=0;  
  64.     while(bfs()){  
  65.    //     printf("here!\n");  
  66.         res+=dfs(0,inf);  
  67.     }  
  68.     return res;  
  69. }  
  70. int main(){  
  71.     init();  
  72.     int p,a,b,c,sum=0;  
  73.     scanf("%d%d",&n,&m);  
  74.     T=n+m+1;//汇点  
  75.     for(int i=1;i<=n;i++){  
  76.         scanf("%d",&p);  
  77.         insert(i+m,T,p);  //课程放右边
  78.         insert(T,i+m,0);  
  79.     }  
  80.     for(int i=1;i<=m;i++){  
  81.         scanf("%d%d%d",&a,&b,&c);  
  82.         sum+=c;  
  83.         insert(i,a+m,inf);   
  84.         insert(a+m,i,0);  
  85.         insert(i,b+m,inf);  
  86.         insert(b+m,i,0);  
  87.         insert(0,i,c);   //用户放左边
  88.         insert(i,0,0);  
  89.     }  
  90.     printf("%d\n",sum-dinic());  
  91.     return 0;  
  92. }  

猜你喜欢

转载自blog.csdn.net/m0_38033475/article/details/80173037
今日推荐