洛谷 P3386【模板】二分图最大匹配
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 505;
int mp[N][N],link[N],vis[N];
int n,m,e,u,v,ans;
bool dfs(int x)
{
for(int i=1; i<=m; i++){
if(!vis[i] && mp[x][i]){
vis[i] = 1;
if(!link[i] || dfs(link[i])){
link[i] = x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d%d%d",&n,&m,&e);
for(int i=0; i<e; i++){
scanf("%d%d",&u,&v);
mp[u][v] = 1;
}
for(int i=1; i<=n; i++) {
memset(vis,0,sizeof(vis));
ans += dfs(i);
}
printf("%d",ans);
return 0;
}
洛谷 P2756飞行员配对方案问题
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 105;
int mp[N][N],vis[N],link[N];
int n,m,u,v,ans;
bool dfs(int x)
{
for(int i=1; i<=n; i++){
if(!vis[i] && mp[x][i]){
vis[i] = 1;
if(!link[i] || dfs(link[i])){
link[i] = x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d%d",&m,&n);
n-=m;
while(scanf("%d%d",&u,&v)){
if(u == -1 && v == -1) break;
mp[u][v-m] = 1;
}
for(int i=1; i<=m; i++) {
memset(vis,0,sizeof(vis));
ans += dfs(i);
}
printf("%d\n",ans);
for(int i=1; i<=n; i++){
if(link[i]) printf("%d %d\n",link[i],i+m);
}
return 0;
}
洛谷 P1129 [ZJOI2007] 矩阵游戏
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 205;
int mp[N][N],vis[N],link[N];
int t,n,ans;
bool dfs(int x)
{
for(int i=1; i<=n; i++){
if(!vis[i] && mp[x][i]){
vis[i] = 1;
if(!link[i] || dfs(link[i])){
link[i] = x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d",&t);
while(t--){
memset(link,0,sizeof(link));
ans = 0;
scanf("%d",&n);
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
scanf("%d",&mp[i][j]);
}
}
for(int i=1; i<=n; i++){
memset(vis,0,sizeof(vis));
ans += dfs(i);
}
printf(ans == n ? "Yes\n" : "No\n");
}
return 0;
}
洛谷P1559 运动员最佳匹配问题
两种敲代码方法,一种dfs完算tmp,一种在dfs中算tmp。不确定是否一种比另一种更优,这道题后者时间占优,然而下一道题洛谷 P4014 分配问题前者时间占优。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 205,INF = 0x7fffffff;
int mp[N][N],lx[N],ly[N],visx[N],visy[N],link[N];
int n,tmp,v;
bool dfs(int x)
{
visx[x] = 1;
for(int i=1; i<=n; i++){
if(!visy[i] && lx[x]+ly[i]==mp[x][i]){
visy[i] = 1;
if(!link[i] || dfs(link[i])){
link[i] = x;
return true;
}
}
}
return false;
}
int one()
{
int ans = 0;
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
lx[i] = std::max(lx[i],mp[i][j]);
}
for(int i=1; i<=n; i++){
while(true){
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
tmp = INF;
if(dfs(i)) break;
for(int i=1; i<=n; i++) if(visx[i]){
for(int j=1; j<=n; j++) if(!visy[j]){
tmp = std::min(tmp,lx[i]+ly[j]-mp[i][j]);
}
}
for(int j=1; j<=n; j++){
if(visx[j]) lx[j] -= tmp;
if(visy[j]) ly[j] += tmp;
}
}
}
for(int i=1; i<=n; i++){
ans += ly[i] + lx[link[i]];
//std::cout << "ly[" << i << "] = " << ly[i] << " lx[" << link[i] << "] = " << lx[link[i]] << " ans = " << ans << std::endl;
}
return ans;
}
int main()
{
//freopen("D:\\EdgeDownloadPlace\\P4014_1.in","r",stdin);
scanf("%d",&n);
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
scanf("%d",&v);
mp[i][j] = -v;
}
for(int i=0; i<N; i++) lx[i] = -INF;
printf("%d\n",-one());
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
mp[i][j] = -mp[i][j];
}
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(link,0,sizeof(link));
printf("%d\n",one());
return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 23,INF = 0x7fffffff;
int mp[N][N],vm[N],vf[N],vism[N],visf[N],link[N];
int n,v,ans,tmp;
bool dfs(int x)
{
vism[x] = 1;
for(int i=1; i<=n; i++){
if(!visf[i]){
int t = vm[x]+vf[i]-mp[x][i];
if(t==0){
visf[i] = 1;
if(!link[i] || dfs(link[i])){
link[i] = x;
return true;
}
}
else if(t>0){
tmp = std::min(t,tmp);
}
}
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) {
scanf("%d",&mp[i][j]);
}
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) {
scanf("%d",&v);
mp[j][i] *= v;
}
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) {
vm[i] = std::max(vm[i],mp[i][j]);
}
for(int i=1; i<=n; i++){
while(true){
memset(visf,0,sizeof(visf));
memset(vism,0,sizeof(vism));
tmp = INF;
if(dfs(i))break;
for(int i=1; i<=n; i++){
if(visf[i]) vf[i] += tmp;
if(vism[i]) vm[i] -= tmp;
}
}
}
for(int i=1; i<=n; i++){
ans += vf[i] + vm[link[i]];
}
printf("%d",ans);
return 0;
}
洛谷 P4014 分配问题
全WA,我的输出莫名其妙出现了"-",洛谷判题机的锅?
破案了,one()里的ans没初始化,Windows自动给个0,Linux就挂了,初始化成0就好了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <map>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
typedef long long int LL;
const int N = 105,INF = 0x7fffffff;
int mp[N][N],lx[N],ly[N],visx[N],visy[N],link[N];
int n,tmp,v;
bool dfs(int x)
{
visx[x] = 1;
for(int i=1; i<=n; i++){
if(!visy[i] && lx[x]+ly[i]==mp[x][i]){
visy[i] = 1;
if(!link[i] || dfs(link[i])){
link[i] = x;
return true;
}
}
}
return false;
}
int one()
{
int ans;
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
lx[i] = std::max(lx[i],mp[i][j]);
}
for(int i=1; i<=n; i++){
while(true){
memset(visx,0,sizeof(visx));
memset(visy,0,sizeof(visy));
tmp = INF;
if(dfs(i)) break;
for(int i=1; i<=n; i++){
if(visx[i]){
for(int j=1; j<=n; j++){
if(!visy[j]){
tmp = std::min(tmp,lx[i]+ly[j]-mp[i][j]);
}
}
}
}
for(int j=1; j<=n; j++){
if(visx[j]) lx[j] -= tmp;
if(visy[j]) ly[j] += tmp;
}
}
}
for(int i=1; i<=n; i++){
ans += ly[i] + lx[link[i]];
}
return ans;
}
int main()
{
//freopen("D:\\EdgeDownloadPlace\\P4014_1.in","r",stdin);
scanf("%d",&n);
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
scanf("%d",&v);
mp[i][j] = -v;
}
for(int i=0; i<N; i++) lx[i] = -INF;
printf("%d\n",-one());
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){
mp[i][j] = -mp[i][j];
}
memset(lx,0,sizeof(lx));
memset(ly,0,sizeof(ly));
memset(link,0,sizeof(link));
printf("%d\n",one());
return 0;
}
洛谷 P1640连续攻击游戏
匈牙利优化 每次memset置零vis数组太慢了,TLE,直接开一个变量timmer当作时间计数,当timmer-vis[x]>0就说明在这次dfs中x节点没有访问过。
.
初始timmer为1, 每次dfs后timmer自增1
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
typedef long long int LL;
const int INF = 0x7fffffff, SCF = 0x3fffffff;
const int N = 1e6+5, M = 220, K = 1e6+4;
int head[N],link[N],vis[N];
int n,idx,a,b,timmer;
struct Edge
{
int to,nxt;
}edg[N<<1];
void addE(int fr,int to)
{
edg[idx].to = to;
edg[idx].nxt = head[fr];
head[fr] = idx++;
}
bool dfs(int x)
{
for(int e=head[x]; e; e=edg[e].nxt){
int y = edg[e].to;
if(timmer-vis[y]>0){
vis[y] = timmer;
if(!link[y] || dfs(link[y])){
link[y] = x;
return true;
}
}
}
return false;
}
int main()
{
idx = 2;
scanf("%d",&n);
for(int i=1; i<=n; i++){
scanf("%d%d",&a,&b);
addE(a,i);
addE(b,i);
}
int i;
for(i=1; i<=n; i++){
timmer = i;
if(!dfs(i)) break;
}
printf("%d",i-1);
return 0;
}