图论:带花树算法-一般图最大权匹配
二分图最大权匹配是KM算法,我可以想到可行顶标和相等子图
一般图的最大权匹配还是带花树算法
不带权的匹配默认权是1
1 #include <bits/stdc++.h> 2 #define N 810 3 using namespace std; 4 typedef long long ll; 5 inline int read() 6 { 7 int x=0,f=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} 10 return x*f; 11 } 12 struct edge{int u,v,w;}mps[N][N]; 13 int n,m,mat[N],pre[N],bl[N],fa[N],tim;ll totw=0; 14 int sign[N],lab[N],slacku[N],blofm[N][N],tot,mx; 15 vector <int> leaves[N]; 16 int q[N],hd; 17 inline int calc_e(const edge &e) 18 { 19 return lab[e.u]+lab[e.v]-mps[e.u][e.v].w*2; 20 } 21 inline void updata(int u,int x) 22 { 23 if(!slacku[x]||calc_e(mps[u][x])<calc_e(mps[slacku[x]][x])) 24 slacku[x]=u; 25 } 26 inline void calc_slack(int x) 27 { 28 slacku[x]=0; 29 for(int i=1;i<=n;i++) 30 if(mps[i][x].w>0&&fa[i]!=x&&sign[fa[i]]==0) 31 updata(i,x); 32 } 33 inline void q_push(int x) 34 { 35 if(x<=n) q[++hd]=x; 36 else for(int i=0;i<(int)leaves[x].size();i++) 37 q_push(leaves[x][i]); 38 } 39 inline int get_lca(int x, int y) 40 { 41 if(tim=100000000) 42 memset(bl,0,sizeof bl),tim=0; 43 for(++tim;x||y;swap(x,y)) if(x) 44 { 45 if(bl[x]==tim) return x; 46 bl[x]=tim; x=fa[mat[x]]; 47 if(x) x=fa[pre[x]]; 48 } 49 return 0; 50 } 51 inline void set_fa(int x,int y) 52 { 53 fa[x]=y; if(x>n) 54 for(int i=0;i<(int)leaves[x].size();i++) 55 set_fa(leaves[x][i],y); 56 } 57 inline void set_mat(int x,int y) 58 { 59 mat[x]=mps[x][y].v; 60 if(x<=n) return ; 61 int xr=blofm[x][mps[x][y].u]; 62 int pr=find(leaves[x].begin(),leaves[x].end(),xr)-leaves[x].begin(); 63 if(pr%2==1) 64 reverse(leaves[x].begin()+1, leaves[x].end()), 65 pr=(int)leaves[x].size()-pr; 66 for(int i=0;i<pr;i++) 67 set_mat(leaves[x][i],leaves[x][i^1]); 68 set_mat(xr,y); 69 rotate(leaves[x].begin(),leaves[x].begin()+pr,leaves[x].end()); 70 } 71 inline void blossom_blooms(int x) 72 { 73 for(int i=0;i<(int)leaves[x].size();i++) 74 { 75 if(leaves[x][i]>n&&!lab[leaves[x][i]]) 76 blossom_blooms(leaves[x][i]); 77 else set_fa(leaves[x][i],leaves[x][i]); 78 } 79 fa[x]=0; 80 } 81 inline void blossom_make(int u,int lca,int v) 82 { 83 int x=n+1; while(x<=tot&&fa[x]) x++; 84 if(x>tot) tot++; 85 lab[x]=sign[x]=0; 86 mat[x]=mat[lca]; leaves[x].clear(); 87 leaves[x].push_back(lca); 88 for(int i=u;i!=lca;i=fa[pre[fa[mat[i]]]]) 89 leaves[x].push_back(i),leaves[x].push_back(fa[mat[i]]),q_push(fa[mat[i]]); 90 reverse(leaves[x].begin()+1, leaves[x].end()); 91 for(int i=v;i!=lca;i=fa[pre[fa[mat[i]]]]) 92 leaves[x].push_back(i),leaves[x].push_back(fa[mat[i]]),q_push(fa[mat[i]]); 93 set_fa(x,x); 94 for(int i=1;i<=tot;i++) 95 mps[x][i].w=mps[i][x].w=0, blofm[x][i]=0; 96 for(int i=0;i<(int)leaves[x].size();i++) 97 { 98 int xs=leaves[x][i]; 99 for(int j=1;j<=tot;j++) 100 if(!mps[x][j].w||calc_e(mps[xs][j])<calc_e(mps[x][j])) 101 mps[x][j]=mps[xs][j],mps[j][x]=mps[j][xs]; 102 for(int j=1;j<=tot;j++) 103 if(blofm[xs][j]) blofm[x][j]=xs; 104 } 105 calc_slack(x); 106 } 107 inline void link(int x,int y) 108 { 109 while(1) 110 { 111 int xx=fa[mat[x]]; 112 set_mat(x,y); 113 if(!xx) return ; 114 set_mat(xx,fa[pre[xx]]); 115 x=fa[pre[xx]]; y=xx; 116 } 117 } 118 inline int deal_edge(const edge &e) 119 { 120 int u=fa[e.u],v=fa[e.v]; 121 if(sign[v]==-1) //unsigned 122 { 123 pre[v]=e.u; // cause we bfs all vertices tegother,we dont' need to discuss two situation 124 sign[v]=1; sign[fa[mat[v]]]=0; 125 slacku[v]=slacku[fa[mat[v]]]=0; 126 q_push(fa[mat[v]]); 127 } 128 else if(!sign[v]) //S signed vertex 129 { 130 int lca=get_lca(u,v); 131 if(!lca) 132 { 133 link(u,v); link(v,u); //connected! new argument. 134 for(int i=n+1;i<=tot;i++) 135 if(fa[i]==i&&lab[i]==0) 136 blossom_blooms(i); // flower may not be a flower any more so we blossom blooms! 137 return 1; 138 } 139 else blossom_make(u,lca,v); // form a new flower! 140 } 141 return 0; 142 } 143 inline void blossom_bloom_1(int x) 144 { 145 146 for(int i=0;i<(int)leaves[x].size();i++) 147 set_fa(leaves[x][i],leaves[x][i]); 148 int xr=blofm[x][mps[x][pre[x]].u]; 149 int pr=find(leaves[x].begin(), leaves[x].end(),xr)-leaves[x].begin(); 150 if(pr%2==1) 151 reverse(leaves[x].begin()+1, leaves[x].end()), 152 pr=(int)leaves[x].size()-pr; 153 for(int i=0;i<pr;i+=2) 154 { 155 int u=leaves[x][i],v=leaves[x][i+1]; 156 pre[u]=mps[v][u].u; 157 sign[u]=1; sign[v]=0; 158 slacku[u]=0; calc_slack(v); q_push(v); 159 } 160 sign[xr]=1; pre[xr]=pre[x]; 161 for(int i=pr+1;i<(int)leaves[x].size();i++) 162 { 163 int u=leaves[x][i]; 164 sign[u]=-1; calc_slack(u); 165 } 166 fa[x]=0; 167 } 168 inline int match() 169 { 170 for(int i=1;i<=tot;i++) slacku[i]=0,sign[i]=-1; 171 hd=0; for(int i=1;i<=tot;i++) 172 if(fa[i]==i&&!mat[i]) 173 slacku[i]=pre[i]=sign[i]=0,q_push(i); 174 if(!hd) return 0; 175 while(1) 176 { 177 for(int i=1;i<=hd;i++) 178 { 179 int lx=q[i]; for(int j=1;j<=n;j++) 180 if(mps[lx][j].w>0&&fa[lx]!=fa[j]) 181 { 182 if(!calc_e(mps[lx][j])) 183 { 184 if(deal_edge(mps[lx][j])) 185 return 1; 186 } 187 else if(sign[fa[j]]!=1) updata(lx,fa[j]); 188 } 189 } 190 int d=0x3fffffff; 191 for(int i=1;i<=n;i++) if(!sign[fa[i]]) 192 d=min(d,lab[i]); 193 for(int i=n+1;i<=tot;i++) 194 if(fa[i]==i&&sign[i]==1) 195 d=min(lab[i]/2,d); 196 for(int i=1;i<=tot;i++) if(fa[i]==i&&slacku[i]) 197 { 198 if(sign[i]==-1) d=min(calc_e(mps[slacku[i]][i]),d); 199 else if(sign[i]==0) d=min(calc_e(mps[slacku[i]][i])/2,d); 200 } 201 for(int i=1;i<=n;i++) 202 if(sign[fa[i]]==0) lab[i]-=d; 203 else if (sign[fa[i]]==1) lab[i]+=d; 204 for(int i=n+1;i<=tot;i++) 205 if(fa[i]==i) 206 { 207 if(sign[i]==0) lab[i]+=d*2; 208 else if(sign[i]==1) lab[i]-=d*2; 209 } 210 hd=0; 211 for(int i=1;i<=n;i++) if(!lab[i]) return 0; //all vetices matched,single vetices's label = 0 212 for(int i=1;i<=tot;i++) 213 if(fa[i]==i&&slacku[i]&&fa[slacku[i]]!=i&&calc_e(mps[slacku[i]][i])==0) 214 /*new edge*/ if(deal_edge(mps[slacku[i]][i])) return 1; 215 for(int i=n+1;i<=tot;i++) 216 if(fa[i]==i&&sign[i]==1&&!lab[i]) 217 blossom_bloom_1(i); 218 } 219 return 0; 220 } 221 inline void solve() 222 { 223 for(int i=1;i<=n;i++) mat[i]=0; 224 tot=n; hd=totw=0; 225 for(int i=0;i<=n;i++) fa[i]=i,leaves[i].clear(); 226 for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) 227 blofm[i][j]=(i==j? i:0); 228 for(int i =1;i<=n;i++) lab[i]=mx; //init label 229 while(match()); 230 for(int i=1;i<=n;i++) if(mat[i]&&mat[i]<i) 231 totw+=mps[i][mat[i]].w; 232 } 233 int main() 234 { 235 n=read(); m=read(); 236 for(int i=1;i<=n;i++) 237 for(int j=1;j<=n;j++) 238 mps[i][j]=(edge){i,j,0}; 239 for(int i=1;i<=m;i++) 240 { 241 int u=read(), v=read(), w=read(); 242 mps[u][v].w=mps[v][u].w=w; mx=max(mx,w); 243 } 244 solve(); printf("%lld\n",totw); 245 for(int i=1;i<=n;i++) 246 printf("%d ",mat[i]); 247 puts(""); 248 return 0; 249 }
代码量简直了