zoukankan      html  css  js  c++  java
  • 二分图最大权匹配 费用流&KM

    费用流 建图时额外添加一个点A(左->A:(1,0) A->T:(inf,0))来保证满流 边少点多较快 边多的情况下表现很差

     1 #include<cstdio> 
     2 #include<cstring>
     3 #include<cmath>
     4 #include<ctime>
     5 #include<iostream>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<set>
     9 #define inf (1ll<<(61ll))
    10 #define l(a) ((a)<<1)
    11 #define r(a) ((a)<<1|1)
    12 #define b(a) (1<<(a))
    13 #define rep(i,a,b) for(int i=a;i<=(b);i++)
    14 #define clr(a) memset(a,0,sizeof(a))
    15 typedef long long ll;
    16 using namespace std;
    17 int readint(){
    18     int t=0,f=1;char c=getchar();
    19     while(!isdigit(c)){
    20         if(c=='-') f=-1;
    21         c=getchar();
    22     }
    23     while(isdigit(c)){
    24         t=(t<<3)+(t<<1)+c-'0';
    25         c=getchar();
    26     }
    27     return t*f;
    28 }
    29 const int maxn=1009,maxe=400009;
    30 int n,m,en,S,A,T;
    31 ll d[maxn];
    32 ll ans;
    33 struct edge{
    34     ll v,w,c;
    35     edge*next,*r;
    36 }E[maxe],*pt=E,*fir[maxn],*cur[maxn],*rev[maxn];
    37 void add(int u,int v,int w,int c){
    38     pt->v=v;pt->w=w;pt->c=c;
    39     pt->next=fir[u];fir[u]=pt++;
    40 }
    41 void addedge(int u,int v,int w,int c){
    42     add(u,v,w,c);add(v,u,0,-c);
    43     fir[u]->r=fir[v];fir[v]->r=fir[u];
    44 }
    45 bool p[maxn];
    46 ll spfa(){
    47     queue<int>Q;clr(p);
    48     rep(i,S,T) d[i]=-inf;
    49     Q.push(S);p[S]=1;d[S]=0;
    50     while(!Q.empty()){
    51         int x=Q.front();Q.pop();p[x]=0;
    52         for(edge*e=fir[x];e;e=e->next) if(e->w){
    53             if(d[e->v]<d[x]+e->c){
    54                 d[e->v]=d[x]+e->c;
    55                 rev[e->v]=e;
    56                 if(!p[e->v]){
    57                     Q.push(e->v);p[e->v]=1;
    58                 }
    59             }
    60         }
    61     }
    62     if(d[T]==-inf) return 0;
    63     for(edge*e=rev[T];e;e=rev[e->r->v]){
    64         e->w-=1;e->r->w+=1;
    65     }
    66     return d[T];
    67 }
    68 void Cal(){
    69     ll t;
    70     while(t=spfa()) ans+=t;
    71 }
    72 int main(){
    73     //freopen("#input.txt","r",stdin);
    74     //freopen("#output.txt","w",stdout);
    75     n=readint();m=readint();en=readint();S=0;A=n+m+1;T=A+1;
    76     rep(i,1,en){
    77         int U=readint(),V=readint(),C=readint();
    78         addedge(U,n+V,1,C);
    79     }
    80     rep(i,1,n) addedge(S,i,1,0);
    81     rep(i,1,m) addedge(n+i,T,1,0);
    82     rep(i,1,n) addedge(i,A,1,0);addedge(A,T,1000009,0);
    83     Cal();
    84     cout<<ans<<endl;
    85     rep(i,1,n){
    86         int f=0;
    87         for(edge*e=fir[i];e;e=e->next){
    88             if(!e->w&&e->v!=A&&e->v!=S) f=e->v-n;
    89         }
    90         printf("%d",f);putchar(i==n?'
    ':' ');
    91     }
    92     //fclose(stdin);
    93     //fclose(stdout);
    94     return 0;
    95 }
    费用流

    km 调了一个下午 半个晚上你敢信?先写了一个貌似n^3的n^4 后来膜着tle的代码写出正确n^3 有空再重新复习敲一下

      1 #include<cstdio> 
      2 #include<cstring>
      3 #include<cmath>
      4 #include<ctime>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<set>
      9 #define inf (0x7fffffffll)
     10 #define l(a) ((a)<<1)
     11 #define r(a) ((a)<<1|1)
     12 #define b(a) (1<<(a))
     13 #define rep(i,a,b) for(int i=a;i<=(b);i++)
     14 #define clr(a) memset(a,0,sizeof(a))
     15 typedef long long ll;
     16 typedef unsigned long long ull;
     17 using namespace std;
     18 int readint(){
     19     int t=0,f=1;char c=getchar();
     20     while(!isdigit(c)){
     21         if(c=='-') f=-1;
     22         c=getchar();
     23     }
     24     while(isdigit(c)){
     25         t=(t<<3)+(t<<1)+c-'0';
     26         c=getchar();
     27     }
     28     return t*f;
     29 }
     30 const int maxn=509;
     31 int n,m,en,now,lp[maxn],rp[maxn],pre[maxn],ld[maxn],rd[maxn],a[maxn],w[maxn][maxn],lc[maxn],rc[maxn];;
     32 ll ans;
     33 queue<int>Q;
     34 bool Bfs(){
     35     while(!Q.empty()){
     36         int u=Q.front();Q.pop();
     37         rep(v,1,m) if(rc[v]!=now){
     38             int t=ld[u]+rd[v]-w[u][v];
     39             if(!t){
     40                 pre[v]=u;
     41                 if(!rp[v]){
     42                     int V=v,tmp;
     43                     for(int U=u;V;U=pre[V]){
     44                         tmp=lp[U];lp[U]=V;rp[V]=U;V=tmp;
     45                     }
     46                     return 1;
     47                 }
     48                 rc[v]=now;
     49                 if(lc[rp[v]]!=now){
     50                     lc[rp[v]]=now;Q.push(rp[v]);
     51                 }
     52             }else if(t<a[v]) a[v]=t,pre[v]=u;
     53         }
     54     }
     55     return 0;
     56 }
     57 void KM(){
     58     rep(S,1,n){
     59         rep(i,1,m) a[i]=inf;clr(pre);
     60         while(!Q.empty()) Q.pop();Q.push(S);lc[S]=++now;
     61         for(;;){
     62             if(Bfs()) break;
     63             int del=inf;
     64             rep(i,1,m) if(rc[i]!=now) del=min(del,a[i]);
     65             rep(i,1,n) if(lc[i]==now) ld[i]-=del;
     66             rep(i,1,m) if(rc[i]==now) rd[i]+=del;else if(a[i]<inf) a[i]-=del;
     67             bool flag=0;
     68             rep(i,1,m) if(rc[i]!=now&&!a[i]){
     69                 if(!rp[i]){
     70                     int V=i,tmp;
     71                     for(int U=pre[i];V;U=pre[V]){
     72                         tmp=lp[U];lp[U]=V;rp[V]=U;V=tmp;
     73                     }
     74                     flag=1;break;
     75                 }
     76                 rc[i]=now;
     77                 if(lc[rp[i]]!=now){
     78                     lc[rp[i]]=now;Q.push(rp[i]);//将新增的点加入队列 避免重复的去匈牙利
     79                 }
     80             }
     81             if(flag) break;
     82         }    
     83     }
     84     rep(i,1,m) if(rp[i]) ans+=w[rp[i]][i];
     85     cout<<ans<<endl;
     86     rep(i,1,n){
     87         printf("%d",w[i][lp[i]]?lp[i]:0);
     88         putchar(i==n?'
    ':' ');
     89     }
     90 }
     91 int main(){
     92     //freopen("#input.txt","r",stdin);
     93     //freopen("#output.txt","w",stdout);
     94     n=readint();m=readint();en=readint();
     95     if(m<n) m=n;
     96     while(en--){
     97         int u=readint(),v=readint();
     98         w[u][v]=readint();ld[u]=max(ld[u],w[u][v]);
     99     }
    100     KM();
    101     //fclose(stdin);
    102     //fclose(stdout);
    103     return 0;
    104 }
    KM算法 
      1 #include<cstdio> 
      2 #include<cstring>
      3 #include<cmath>
      4 #include<ctime>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<set>
      9 #define inf (0x7fffffff)
     10 #define l(a) ((a)<<1)
     11 #define r(a) ((a)<<1|1)
     12 #define b(a) (1<<(a))
     13 #define rep(i,a,b) for(int i=a;i<=(b);i++)
     14 #define clr(a) memset(a,0,sizeof(a))
     15 typedef long long ll;
     16 typedef unsigned long long ull;
     17 using namespace std;
     18 int readint(){
     19     int t=0,f=1;char c=getchar();
     20     while(!isdigit(c)){
     21         if(c=='-') f=-1;
     22         c=getchar();
     23     }
     24     while(isdigit(c)){
     25         t=(t<<3)+(t<<1)+c-'0';
     26         c=getchar();
     27     }
     28     return t*f;
     29 }
     30 const int maxn=509;
     31 int n,m,en,now,pre[maxn],ld[maxn],rd[maxn],lc[maxn],rc[maxn],lp[maxn],rp[maxn],a[maxn],w[maxn][maxn];
     32 queue<int>Q;
     33 bool Bfs(){
     34     while(!Q.empty()){
     35         int u=Q.front();Q.pop();
     36         rep(v,1,m) if(rc[v]!=now){
     37             int t=ld[u]+rd[v]-w[u][v];//u,v不能写错 
     38             if(!t){
     39                 pre[v]=u;
     40                 if(!rp[v]){
     41                     rp[v]=u;
     42                     int V=v,tmp;
     43                     for(int U=u;V;U=pre[V]){
     44                         tmp=lp[U];lp[U]=V;rp[V]=U;V=tmp;
     45                     }
     46                     return 1;
     47                 }
     48                 rc[v]=now;//注意 
     49                 if(lc[rp[v]]!=now){
     50                     lc[rp[v]]=now;Q.push(rp[v]);
     51                 }
     52             }else if(a[v]>t){
     53                 a[v]=t;pre[v]=u;
     54             }
     55         }
     56     }
     57     return 0;
     58 }
     59 void KM(){
     60     rep(S,1,n){
     61         while(!Q.empty()) Q.pop();
     62         rep(i,1,m) a[i]=inf;clr(pre);
     63         Q.push(S);lc[S]=++now;
     64         for(;;){
     65             bool flag=0;
     66             if(Bfs()) break;
     67             int del=inf;
     68             rep(i,1,m) if(rc[i]!=now) del=min(del,a[i]);
     69             rep(i,1,n) if(lc[i]==now) ld[i]-=del;
     70             rep(i,1,m) if(rc[i]==now) rd[i]+=del;else if(a[i]<inf) a[i]-=del;//理解 
     71             rep(i,1,m) if(rc[i]!=now&&!a[i]){
     72                 if(!rp[i]){
     73                     int V=i,tmp;
     74                     for(int U=pre[i];V;U=pre[V]){
     75                         tmp=lp[U];lp[U]=V;rp[V]=U;V=tmp;
     76                     }
     77                     flag=1;break;
     78                 }
     79                 rc[i]=now;//注意 
     80                 if(lc[rp[i]]!=now){
     81                     lc[rp[i]]=now;Q.push(rp[i]);//将后面的BFS合起来 避免无意义的BFS 
     82                 }
     83             } 
     84             if(flag) break;
     85         }
     86     }
     87     ll ans=0;
     88     rep(i,1,n) if(lp[i]) ans+=w[i][lp[i]];
     89     cout<<ans<<endl;
     90     rep(i,1,n){
     91         printf("%d",w[i][lp[i]]?lp[i]:0);
     92         putchar(i==n?'
    ':' ');
     93     }
     94 }
     95 int main(){
     96     //freopen("#input.txt","r",stdin);
     97     //freopen("#output.txt","w",stdout);
     98     n=readint();m=readint();en=readint();
     99     if(m<n) m=n;
    100     while(en--){
    101         int u=readint(),v=readint();
    102         w[u][v]=readint();ld[u]=max(ld[u],w[u][v]);
    103     }
    104     KM();
    105     //fclose(stdin);
    106     //fclose(stdout);
    107     return 0;
    108 }
    KM Review

    有几个要注意的点!

  • 相关阅读:
    关于c语言的一个小bug(c专家编程)
    A10 平板开发一硬件平台搭建
    A10 平板开发二搭建Android开发环境
    hdu
    如何选择发现自己是否适合科研?
    屌丝程序员与房子
    一步一步学数据结构之n--n(Prim算法)
    pat 1049 Counting Ones
    add-strings
    这篇讲PHP的讲的有些道理 & mb_substr & 中文处理
  • 原文地址:https://www.cnblogs.com/chensiang/p/7854354.html
Copyright © 2011-2022 走看看