洛谷P1640 连续攻击游戏+二分图匹配
本题是个二分图匹配问题。
首先我们来复习一下匈牙利算法:
用临接矩阵写的匈牙利:
Code:(洛谷P3386)
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define ll long long #define INF 0x3f3f3f3f #define maxn 1001 using namespace std; int match[maxn*100],n,m,e,ans,map[maxn][maxn],vis[maxn*100]; bool dfs(int x){ for(int i=1;i<=m;i++){ if(map[x][i]==1&&vis[i]==0){ vis[i]=1; if(match[i]==0||dfs(match[i])==1){ match[i]=x; return 1; } } } return 0; } int main(){ cin>>n>>m>>e; for(int i=1;i<=e;i++){ int x,y; cin>>x>>y; if(x<=n&&y<=m){ map[x][y]=1; } } for(int i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); if(dfs(i)==1){ ans++; } } cout<<ans; return 0; }
现在我们来看这个题:
把物品属性a,b,从a,b向i连个有向边,然后一部分是物品一部分是序号,直接匹配即可。
Code:
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define ll long long #define maxn 100010 using namespace std; struct Edge{ int nxt,to; }edge[2000010]; int n,num_edge,ans,vis[10005],head[10005],match[1000010]; inline void addedge(int from,int to){ edge[++num_edge].to=to; edge[num_edge].nxt=head[from]; head[from]=num_edge; } bool dfs(int x){ if(vis[x]) return 0; vis[x]=1; for(int i=head[x];i;i=edge[i].nxt){ int y=edge[i].to; // if(!vis[y]){ // vis[y]=1; if(!match[y]||dfs(match[y])){ match[y]=x; return 1; } // } } return 0; } inline void check(){ for(int i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); if(dfs(i)){ ans++; } else break; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ int x,y; scanf("%d%d",&x,&y); //addedge(x,y); addedge(x,i); addedge(y,i); } check(); printf("%d",ans); return 0; }