专题链接kuangbin专题十 匹配问题
快速跳转
- 题目
- 个人模板
- 匈牙利算法
- 可匹配多个的匈牙利算法
- KM算法
- AC代码
- Fire Net
- The Accomodation of Students
- Courses
- 棋盘游戏
- Swap
- Rain on your Parade
- Oil Skimming
- Antenna Placement
- Strategic Game
- Air Raid
- Treasure Exploration
- Cat VS Dog
- Jamie's Contact Groups
- Optimal Milking
- Steady Cow Assignment
- 奔小康赚大钱
- Tour
- Work Scheduling
- Boke and Tsukkomi
题目
HDU 1045 Fire Net
HDU 2444 The Accomodation of Students
HDU 1083 Courses
HDU 1281 棋盘游戏
HDU 2819 Swap
HDU 2389 Rain on your Parade
HDU 4185 Oil Skimming
POJ 3020 Antenna Placement
HDU 1054 Strategic Game
HDU 1151 Air Raid
POJ 2594 Treasure Exploration
HDU 3829 Cat VS Dog
POJ 2289 Jamie’s Contact Groups
POJ 2112 Optimal Milking
POJ 3189 Steady Cow Assignment
HDU 2255 奔小康赚大钱
HDU 3488 Tour
URAL 1099 Work Scheduling
HDU 4687 Boke and Tsukkomi
个人模板
匈牙利算法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define Ri(x) scanf("%d",&x)
#define Rii(x,y) scanf("%d%d",&x,&y)
#define ms0(ar) memset(ar,0,sizeof(ar))
#define ms1(ar) memset(ar,-1,sizeof(ar))
#define pb push_back
const int N=1e3,M=1e4;
int n,p,m,cnt,ans;
int a[N],b[N],fst[N],nxt[M],to[M],lin[N];
bool vis[N];
void add(int x,int y){
to[++cnt]=y;
nxt[cnt]=fst[x];
fst[x]=cnt;
}
bool dfs(int x){
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(!lin[v]||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
}
return 0;
}
int main(){
while(Rii(n,p)){
Ri(m);
rep(i,1,n)
Ri(a[i]);
rep(i,1,p)
Ri(b[i]);
ms0(lin),ms0(fst);
ans=cnt=0;
int u,v;
rep(i,1,m){
Rii(u,v);
add(u,v);
}
rep(i,1,n){
ms0(vis);
if(dfs(a[i])) ans++;
}
cout<<ans<<endl;
}
return 0;
}
可匹配多个的匈牙利算法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define Ri(x) scanf("%d",&x)
#define Rii(x,y) scanf("%d%d",&x,&y)
#define ms0(ar) memset(ar,0,sizeof(ar))
#define ms1(ar) memset(ar,-1,sizeof(ar))
#define pb push_back
const int N=1e3,M=1e4;
int n,p,m,cnt,ans,d;
int a[N],b[N],fst[N],nxt[M],to[M],c[N],lin[N][N];
bool vis[N];
void add(int x,int y){
to[++cnt]=y;
nxt[cnt]=fst[x];
fst[x]=cnt;
}
bool dfs(int x,int d){
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(lin[v][0]<d){
lin[v][++lin[v][0]]=x;
return 1;
}
else
rep(j,1,lin[v][0])
if(dfs(lin[v][j],d)){
lin[v][j]=x;
return 1;
}
}
}
return 0;
}
int main(){
while(Rii(n,p)){
Ri(m);
Ri(d);
rep(i,1,n)
Ri(a[i]);
rep(i,1,p)
Ri(b[i]);
ms0(lin),ms0(fst);
ans=cnt=0;
int u,v;
rep(i,1,m){
Rii(u,v);
add(u,v);
}
rep(i,1,n){
ms0(vis);
if(dfs(a[i],d)) ans++;
}
cout<<ans<<endl;
}
return 0;
}
KM算法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define ms0(ar) memset(ar,0,sizeof ar)
#define ms1(ar) memset(ar,-1,sizeof ar)
#define Ri(x) scanf("%d",&x)
#define Rii(x) scanf("%d%d",&x,&y)
const int N=1e3,INF=0x3f3f3f3f;
int g[N][N],gap[N],exl[N],exr[N],lin[N],n;
bool visl[N],visr[N];
bool dfs(int x){
visl[x]=1;
rep(i,1,n){
if(visr[i]) continue;
int d=exl[x]+exr[i]-g[x][i];
if(!d){
visr[i]=1;
if(!lin[i]||dfs(lin[i])){
lin[i]=x;
return 1;
}
}
else if(gap[i]>d) gap[i]=d;
}
return 0;
}
int main(){
while(Ri(n)){
ms0(lin);
rep(i,1,n)
rep(j,1,n){
Ri(g[i][j]);
exl[i]=max(exl[i],g[i][j]);
}
rep(i,1,n){
rep(j,1,n) gap[j]=INF;
while(1){
ms0(visl),ms0(visr);
if(dfs(i)) break;
int d=INF;
rep(j,1,n)
if(!visr[j]) d=min(d,gap[j]);
rep(j,1,n){
if(visl[j]) exl[j]-=d;
if(visr[j]) exr[j]+=d;
else gap[j]-=d;
}
}
}
int ans=0;
rep(i,1,n) ans+=g[lin[i]][i];
printf("%d\n",ans);
}
return 0;
}
AC代码
Fire Net
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
int n,cnt,a[5][5],b[5][5],line[105],ans,c1,c2;
char p[5][5];
bool vis[105],maps[105][105];
bool dfs(int x){
rep(i,1,c2)
if(maps[x][i]&&!vis[i]){
vis[i]=1;
if((!line[i])||dfs(line[i])){
line[i]=x;
return 1;
}
}
return 0;
}
int main(){
while(cin>>n){
if(!n) break;
cnt=1,ans=0;
memset(maps,0,sizeof(maps));
memset(line,0,sizeof(line));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
rep(i,1,n){
rep(j,1,n){
cin>>p[i][j];
if(p[i][j]=='.') a[i][j]=cnt;
else cnt++;
}
cnt++;
}
c1=cnt;
cnt=1;
rep(i,1,n){
rep(j,1,n)
if(p[j][i]=='.') b[j][i]=cnt,maps[a[j][i]][b[j][i]]=1;
else cnt++;
cnt++;
}
c2=cnt;
rep(i,1,100){
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
cout<<ans<<endl;
}
return 0;
}
The Accomodation of Students
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
const int N=500+5,M=2*N*N;
int n,m,fst[N],nxt[M],line[N],to[M],cnt=0,c[N];
bool vis[N];
void add(int x,int y){
nxt[++cnt]=fst[x];
fst[x]=cnt;
to[cnt]=y;
}
bool xyl(int x){
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if((!line[v])||xyl(line[v])){
line[v]=x;
return 1;
}
}
}
return 0;
}
bool rs(int x,int co){
c[x]=co;
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!c[v]){
if(!rs(v,-co)) return 0;
}
else if(c[v]==co) return 0;
}
return 1;
}
bool eft(){
rep(i,1,n)
if(!c[i])
if(!rs(i,1)) return 0;
return 1;
}
int main(){
while(~scanf("%d%d",&n,&m)){
memset(c,0,sizeof(c));
memset(fst,0,sizeof(fst));
memset(nxt,0,sizeof(nxt));
memset(line,0,sizeof(line));
int u,v;
cnt=0;
rep(i,1,m){
cin>>u>>v;
add(u,v);
add(v,u);
}
bool flag=1;
int ans=0;
if(!eft()) flag=0;
if(flag){
rep(i,1,n){
memset(vis,0,sizeof(vis));
if(c[i]==1&&xyl(i)) ans++;
}
cout<<ans<<endl;
}
else cout<<"No"<<endl;
}
return 0;
}
Courses
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
const int P=100+5,N=300+5;
int p,n,fst[P],to[P*N],line[N],nxt[P*N],sum=0;
void add(int x,int y){
nxt[++sum]=fst[x];
fst[x]=sum;
to[sum]=y;
}
bool vis[N];
bool dfs(int x){
for(int i=fst[x];i;i=nxt[i]){
int s=to[i];
if(!vis[s]){
vis[s]=1;
if(!line[s]||dfs(line[s])){
line[s]=x;
return 1;
}
}
}
return 0;
}
int main(){
int question,cnt,stu;
cin>>question;
while(question--){
cin>>p>>n;
sum=0;
memset(fst,0,sizeof(fst));
memset(nxt,0,sizeof(nxt));
memset(line,0,sizeof(line));
rep(i,1,p){
cin>>cnt;
rep(j,1,cnt){
cin>>stu;
add(i,stu);
}
}
int ans=0;
rep(i,1,p){
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
if(ans==p) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
棋盘游戏
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
const int N=105,K=N*N;
int n,m,k,line[N];
bool maps[N][N],vis[N];
bool dfs(int x){
rep(i,1,m)
if(maps[x][i]&&!vis[i]){
vis[i]=1;
if(!line[i]||dfs(line[i])){
line[i]=x;
return 1;
}
}
return 0;
}
int main(){
int t=0;
while(cin>>n>>m>>k){
memset(maps,0,sizeof(maps));
memset(line,0,sizeof(line));
int u,v,ans=0;
rep(i,1,k){
cin>>u>>v;
maps[u][v]=1;
}
int l=0,cnt=0;
rep(i,1,n){
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
l=ans;
rep(i,1,n)
rep(j,1,m)
if(maps[i][j]){
maps[i][j]=ans=0;
memset(line,0,sizeof(line));
rep(p,1,n){
memset(vis,0,sizeof(vis));
if(dfs(p)) ans++;
}
maps[i][j]=1;
if(ans!=l) cnt++;
}
cout<<"Board "<<++t<<" have "<<cnt<<" important blanks for "<<l<<" chessmen."<<endl;
}
return 0;
}
Swap
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
const int N=105;
int a[N][N],n,fst[N],nxt[N*N],to[N],lin[N],e,cnt,tem,r[N];
struct op{
int x,y;
}ans[N*N];
void add(int x,int y){
to[++e]=y;
nxt[e]=fst[x];
fst[x]=e;
}
bool vis[N];
bool dfs(int x){
rep(i,1,n)
if(a[x][i]&&!vis[i]){
vis[i]=1;
if(!lin[i]||dfs(lin[i])){
lin[i]=x;
r[x]=i;
return 1;
}
}
return 0;
}
int main(){
while(cin>>n){
int temp;
// memset(fst,0,sizeof(fst));
// memset(nxt,0,sizeof(nxt));
memset(lin,0,sizeof(lin));
memset(r,0,sizeof(r));
memset(ans,0,sizeof(ans));
e=0;
rep(i,1,n)
rep(j,1,n){
cin>>a[i][j];
// if(a[i][j]) add(i,j);
}
cnt=tem=0;
rep(i,1,n){
memset(vis,0,sizeof(vis));
if(dfs(i)) tem++;
else break;
}
if(tem<n) cout<<-1<<endl;
else{
rep(i,1,n)
if(r[i]!=i)
rep(j,(i+1),n)
if(r[j]==i){
ans[++cnt].x=i;
ans[cnt].y=r[i];
r[j]=r[i];
break;
}
cout<<cnt<<endl;
rep(i,1,cnt) cout<<"C "<<ans[i].x<<" "<<ans[i].y<<endl;
}
}
return 0;
}
Rain on your Parade
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const int N = 3e3 + 5, M = N * N, INF = 0x3f3f3f3f;
struct E {
int v, next;
} e[M];
struct Node {
double x, y, s;
} a[N], b[N];
int n, m, k, t, len, dis, h[N], mx[N], my[N], dx[N], dy[N];
bool vis[N];
void add(int u, int v) {
e[++len].v = v;
e[len].next = h[u];
h[u] = len;
}
bool bfs() {
queue<int> q;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
//找出未匹配的点 (左边)
for (int i = 1; i <= n; i++) {
if (mx[i] == -1) q.push(i), dx[i] = 0;
}
dis = INF; //初始令增广路为无穷
while (!q.empty()) {
int u = q.front(); q.pop();
if (dx[u] > dis) break; //代表还有比dis更长的增广路 留待下次bfs扩展
for (int j = h[u]; j; j = e[j].next) {
int v = e[j].v;
if (dy[v] == -1) { //代表还未遍历过
dy[v] = dx[u] + 1; //给予层次
if (my[v] == -1) {
dis = dy[v]; //找到增广路
} else {
//如果已经匹配了 就把匹配好的点(左边)放入队列进行扩展
dx[my[v]] = dy[v] + 1;
q.push(my[v]);
}
}
}
}
return dis != INF; //等于INF就未找到增广路
}
bool dfs(int u) {
for (int j = h[u]; j; j = e[j].next) {
int v = e[j].v;
if (vis[v] || dy[v] != dx[u] + 1) continue; //如果未访问且是u的下层次点
vis[v] = true;
if (my[v] != -1 && dy[v] == dis) continue; //如果这个点已经匹配 且找到的增广路已经大于dis
if (my[v] == -1 || dfs(my[v])) {
my[v] = u; mx[u] = v;
return true;
}
}
return false;
}
int getMax() {
int ans = 0;
memset(mx, -1, sizeof(mx));
memset(my, -1, sizeof(my));
while (bfs()) { //查找是否有增广路
memset(vis, false, sizeof(vis)); //对于找到的一条增广路径查询
for (int i = 1; i <= n; i++) {
if (mx[i] == -1 && dfs(i)) ans++; //如果未匹配才去dfs
}
}
return ans;
}
int main() {
scanf("%d", &t);
for (int T = 1; T <= t; T++) {
memset(h, 0, sizeof(h)); len = 0;
scanf("%d%d", &k, &n);
for (int i = 1; i <= n; i++) {
scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].s);
}
scanf("%d", &m);
double x, y;
for (int i = 1; i <= m; i++) {
scanf("%lf%lf", &b[i].x, &b[i].y);
}
for (int i = 1; i <= m; i++) {
x = b[i].x, y = b[i].y;
for (int j = 1; j <= n; j++) {
double fx = a[j].x - x;
double fy = a[j].y - y;
double d = sqrt(fx*fx + fy*fy);
if (d <= k * a[j].s) add(j, i);
}
}
int ans=getMax();
printf("Scenario #%d:\n%d\n\n", T, ans);
}
return 0;
}
Oil Skimming
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
const int N=1205;
int n,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0},a[N][N],fst[N*N],nxt[N*N*2],to[N*N*2],lin[N*N],cnt,ec;
bool vis[N*N];
void add(int x,int y){
to[++ec]=y;
nxt[ec]=fst[x];
fst[x]=ec;
}
bool dfs(int x){
for(int i=fst[x];~i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(lin[v]==-1||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
}
return 0;
}
char g[N][N];
int main(){
int k,ans,cnt1,cnt2;
char tem;
cin>>k;
rep(w,1,k){
memset(fst,-1,sizeof(fst));
memset(nxt,-1,sizeof(nxt));
memset(lin,-1,sizeof(lin));
memset(a,0,sizeof(a));
cin>>n;
cnt=ec=ans=0;
rep(i,1,n)
rep(j,1,n){
cin>>g[i][j];
if((i+j)&1&&g[i][j]=='#') a[i][j]=++cnt;
}
int t=cnt+1;
rep(i,1,n)
rep(j,1,n)
if(g[i][j]=='#'&&!a[i][j]) a[i][j]=++cnt;
ans=0;
rep(i,1,n)
rep(j,1,n)
if((i+j)&1&&a[i][j])
rep(p,0,3){
int x=i+dx[p],y=j+dy[p];
if(x<=n&&x>=1&&y<=n&&y>=1&&a[x][y]) add(a[i][j],a[x][y]);
}
rep(i,1,n*n){
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
cout<<"Case "<<w<<": "<<ans<<endl;
}
return 0;
}
Antenna Placement
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
const int H=45,W=15,P=H*W;
int a[H][W],dx[]={0,0,1,-1},dy[]={1,-1,0,0},fst[P>>1],nxt[P<<1],to[P<<1],lin[P>>1];
int ec,h,w;
bool vis[P>>1];
bool in(int x,int y){
return x>=1&&x<=h&&y>=1&&y<=w;
}
bool dfs(int x){
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(!lin[v]||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
}
return 0;
}
void add(int x,int y){
to[++ec]=y;
nxt[ec]=fst[x];
fst[x]=ec;
}
void made(int x,int y){
int tx,ty;
rep(i,0,3){
tx=x+dx[i],ty=y+dy[i];
if(in(tx,ty)&&a[tx][ty]) add(a[x][y],a[tx][ty]);
}
}
int main(){
int t;
cin>>t;
while(t--){
cin>>h>>w;
char tem;
int cnt1=0,cnt2=0,ans=0;
memset(a,0,sizeof(a));
memset(fst,0,sizeof(fst));
memset(lin,0,sizeof(lin));
ec=0;
rep(i,1,h)
rep(j,1,w){
cin>>tem;
if(tem=='*'){
if((i+j)&1) a[i][j]=++cnt1;
else a[i][j]=++cnt2;
}
}
rep(i,1,h)
rep(j,1,w)
if((i+j)&1&&a[i][j])
made(i,j);
rep(i,1,cnt1){
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}
cout<<cnt1+cnt2-ans<<endl;
}
return 0;
}
Strategic Game
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
//#define me0(ar) memset(ar,0,sizeof(ar))
//#define me1(ar) memset(ar,-1,sizeof(ar))
//#define pb push_back
const int N=1505,M=N*N;
int n,ec;
int fst[N],nxt[M],to[M],lin[N],c[N];
bool g[N][N],vis[N];
void add(int x,int y){
to[++ec]=y;
nxt[ec]=fst[x];
fst[x]=ec;
}
void rs(){
int f[M]={0,0},head=0,tail=1;
c[0]=1;
do{
head++;
int u=f[head];
if(vis[u]) continue;
vis[u]=1;
rep(i,0,n-1)
if(g[u][i]){
f[++tail]=i;
c[i]=-c[u];
if(c[u]==1) add(u,i);
}
}while(head<tail);
}
bool dfs(int x){
for(int i=fst[x];~i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(lin[v]==-1||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
}
return 0;
}
int main(){
int ans;
while(cin>>n){
memset(g,0,sizeof g);
memset(lin,-1,sizeof lin);
memset(fst,-1,sizeof fst);
memset(nxt,-1,sizeof nxt);
ans=ec=0;
rep(i,1,n){
string s;
int nod=0,k=0,p=0,num;
cin>>s;
while(s[p]>='0'&&s[p]<='9') nod*=10,nod+=s[p++]-'0';
p+=2;
while(s[p]>='0'&&s[p]<='9') k*=10,k+=s[p++]-'0';
rep(j,1,k){
cin>>num;
g[num][nod]=g[nod][num]=1;
}
}
memset(vis,0,sizeof vis);
rs();
rep(i,0,n-1)
if(c[i]==1){
memset(vis,0,sizeof vis);
if(dfs(i)) ans++;
}
cout<<ans<<endl;
}
return 0;
}
Air Raid
#include<iostream>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof(ar))
#define me1(ar) memset(ar,-1,sizeof(ar))
#define pb push_back
const int N=245,M=N*N;
int n,k,ec;
int fst[N],nxt[M],to[M],lin[N];
void init(){
ec=0;
me0(fst);
me0(nxt);
me0(to);
me0(lin);
}
void add(int x,int y){
to[++ec]=y;
nxt[ec]=fst[x];
fst[x]=ec;
}
bool vis[N];
bool dfs(int x){
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(!lin[v]||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
}
return 0;
}
int main(){
int t;
cin>>t;
while(t--){
init();
cin>>n>>k;
int sk,ek,ans=0;
rep(i,1,k){
cin>>sk>>ek;
add(sk*2,ek*2-1);
}
rep(i,1,n){
me0(vis);
if(dfs(i*2)) ans++;
}
cout<<n-ans<<endl;
}
return 0;
}
Treasure Exploration
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof(ar))
#define me1(ar) memset(ar,-1,sizeof(ar))
const int N=505,M=5e3+5,MAXM=1e6;
int n,m,ec;
int fst[N<<1],nxt[MAXM],to[MAXM],lin[N<<1];
bool g[N][N],vis[N<<1];
void init(){
ec=0;
me0(g);
me0(fst);
me0(nxt);
me0(to);
me0(lin);
}
void add(int x,int y){
to[++ec]=y;
nxt[ec]=fst[x];
fst[x]=ec;
}
bool dfs(int x){
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(!lin[v]||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
}
return 0;
}
int main(){
while(1){
cin>>n>>m;
init();
if(!n) break;
int u,v,ans=0;
rep(i,1,m){
cin>>u>>v;
g[u][v]=1;
}
rep(i,1,n)
rep(j,1,n)
rep(k,1,n)
if(g[i][k]&&g[k][j]) g[i][j]=1;
rep(i,1,n)
rep(j,1,n)
if(g[i][j]) add(i*2,j*2-1);
rep(i,1,n){
me0(vis);
if(dfs(i*2)) ans++;
}
cout<<n-ans<<endl;
}
return 0;
}
Cat VS Dog
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof(ar))
#define me1(ar) memset(ar,-1,sizeof(ar))
const int N=1005,M=1005,P=2005;
int n,m,p,ec;
int c1[P],c2[P],d1[P],d2[P],fst[N],nxt[P*P],to[P*P],lin[P];
void init(){
ec=0;
me0(c1),me0(c2),me0(d1),me0(d2),me0(fst),me0(nxt),me0(to),me0(lin);
}
void add(int x,int y){
to[++ec]=y;
nxt[ec]=fst[x];
fst[x]=ec;
}
bool vis[P];
bool dfs(int x){
for(int i=fst[x];i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(!lin[v]||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
}
return 0;
}
int main(){
while(cin>>n>>m>>p){
int cntc=-1,cntd=0,ans=0,n1,n2;
init();
char a,b;
rep(i,1,p){
cin>>a>>n1>>b>>n2;
if(a=='C') cntc+=2,c1[cntc]=n1,c2[cntc]=n2;
else cntd+=2,d1[cntd]=n1,d2[cntd]=n2;
}
for(int i=1;i<=cntc;i+=2)
for(int j=2;j<=cntd;j+=2)
if(c2[i]==d1[j]||c1[i]==d2[j]) add(i,j);
for(int i=1;i<=cntc;i+=2){
me0(vis);
if(dfs(i)) ans++;
}
cout<<p-ans<<endl;
}
return 0;
}
Jamie’s Contact Groups
#include<iostream>
#include<cstring>
#include<string>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof(ar))
#define me1(ar) memset(ar,-1,sizeof(ar))
const int N=1e3+5,M=505,E=N*M;
int n,m,cnt,ec,tmp=0;
int fst[N],nxt[E],to[E],lin[M][N];
bool vis[N+M];
void init(){
cnt=ec=0;
me1(fst),me1(nxt);
rep(i,0,m-1) lin[i][0]=0;
}
void add(int x,int y){
to[++ec]=y;
nxt[ec]=fst[x];
fst[x]=ec;
}
bool dfs(int x,int d){
for(int i=fst[x];~i;i=nxt[i]){
int v=to[i];
if(!vis[v]){
vis[v]=1;
if(lin[v][0]<d){
lin[v][++lin[v][0]]=x;
return 1;
}
else
rep(i,1,lin[v][0])
if(dfs(lin[v][i],d)){
lin[v][i]=x;
return 1;
}
}
}
return 0;
}
bool pd(int x){
me0(lin);
rep(i,1,n){
me0(vis);
if(!dfs(i,x)) return 0;
}
return 1;
}
int main(){
while(~scanf("%d%d",&n,&m)){
if(!n) break;
init();
char s=getchar();
rep(i,1,n){
cnt++;
bool flag=0;
int num=0;
while(1){
s=getchar();
if(s=='\n'){
add(cnt,num);
num=0;
break;
}
if(s>='0'&&s<='9') num*=10,num+=s-'0',flag=1;
else if(flag){
add(cnt,num);
num=0;
}
}
}
int l=1,r=n+1,mid;
while(l<r){
mid=(l+r)>>1;
if(pd(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
return 0;
}
Optimal Milking
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof ar)
#define me1(ar) memset(ar,-1,sizeof ar)
const int N=235,INF=0x3f3f3f3f;
struct dot{
int v,w;
}b[N][35];
int a[N][N],lin[35][N];
int k,c,m,ans=0;
bool vis[N];
bool cmp(dot x,dot y){
return x.w<y.w;
}
bool dfs(int x,int d){
rep(i,1,k){
int v=b[x][i].v,w=b[x][i].w;
if(w>d) return 0;
if(vis[v]) continue;
vis[v]=1;
if(lin[v][0]<m){
lin[v][++lin[v][0]]=x;
return 1;
}
else rep(j,1,lin[v][0])
if(dfs(lin[v][j],d)){
lin[v][j]=x;
return 1;
}
}
return 0;
}
bool lt(int d){
me0(lin);
rep(i,1,c){
me0(vis);
if(!dfs(i,d)) return 0;
}
return 1;
}
int main(){
cin>>k>>c>>m;
int kc=k+c,qm=0;
rep(i,1,kc)
rep(j,1,kc){
cin>>a[i][j];
if(i!=j&&!a[i][j]) a[i][j]=INF;
}
rep(p,1,kc)
rep(i,1,kc)
rep(j,1,kc)
if(a[i][p]+a[p][j]<a[i][j]) a[i][j]=a[i][p]+a[p][j];
rep(i,1,c){
rep(j,1,k){
b[i][j].v=j,b[i][j].w=a[k+i][j];
if(a[k+i][j]!=INF) qm=max(qm,a[k+i][j]);
}
sort(b[i]+1,b[i]+k+1,cmp);
}
int l=1,r=qm+1;
while(l<r){
int mid=(l+r)>>1;
if(lt(mid)) r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}
Steady Cow Assignment
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof ar)
#define me1(ar) memser(ar,-1,sizeof ar)
const int N=1e3+5;
int n,b;
int c[N],g[N][N],lin[N][N];
bool vis[N];
bool dfs(int p,int x,int y){
rep(i,x,y){
int v=g[p][i];
if(vis[v]) continue;
vis[v]=1;
if(lin[v][0]<c[v]){
lin[v][++lin[v][0]]=p;
return 1;
}
rep(j,1,lin[v][0])
if(dfs(lin[v][j],x,y)){
lin[v][j]=p;
return 1;
}
}
return 0;
}
bool pd(int x,int y){
me0(lin);
rep(i,1,n){
me0(vis);
if(!dfs(i,x,y)) return 0;
}
return 1;
}
bool op(int d){
rep(i,1,b-d)
if(pd(i,i+d)) return 1;
return 0;
}
int main(){
while(cin>>n>>b){
me0(g);
me0(c);
rep(i,1,n)
rep(j,1,b) cin>>g[i][j];
rep(i,1,b) cin>>c[i];
int l=0,r=b,ans;
while(l<r){
int m=(l+r)>>1;
if(op(m)) r=m;
else l=m+1;
}
cout<<l+1<<endl;
}
return 0;
}
奔小康赚大钱
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof ar)
#define me1(ar) memset(ar,-1,sizeof ar)
const int N=305,INF=0x3f3f3f3f;
int g[N][N],gap[N],exl[N],exr[N],lin[N],n;
bool visl[N],visr[N];
bool dfs(int x){
visl[x]=1;
rep(i,1,n){
if(visr[i]) continue;
int d=exl[x]+exr[i]-g[x][i];
if(!d){
visr[i]=1;
if(!lin[i]||dfs(lin[i])){
lin[i]=x;
return 1;
}
}
else if(gap[i]>d) gap[i]=d;
}
return 0;
}
int main(){
while(cin>>n){
me0(lin);
rep(i,1,n)
rep(j,1,n){
scanf("%d",&g[i][j]);
exl[i]=max(exl[i],g[i][j]);
}
rep(i,1,n){
rep(j,1,n) gap[j]=INF;
while(1){
me0(visl),me0(visr);
if(dfs(i)) break;
int d=INF;
rep(j,1,n)
if(!visr[j]) d=min(d,gap[j]);
rep(j,1,n){
if(visl[j]) exl[j]-=d;
if(visr[j]) exr[j]+=d;
else gap[j]-=d;
}
}
}
int ans=0;
rep(i,1,n) ans+=g[lin[i]][i];
cout<<ans<<endl;
}
return 0;
}
Tour
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef double db;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define me0(ar) memset(ar,0,sizeof ar)
#define me1(ar) memset(ar,-1,sizeof ar)
const int N=405,M=6e4+5,INF=0x3f3f3f3f;
int n,m,cnt,l=INF;
int lin[N],exl[N],exr[N],g[N][N];
bool visl[N],visr[N];
bool dfs(int x){
visl[x]=1;
rep(v,1,n){
if(visr[v]) continue;
int gap=exl[x]+exr[v]-g[x][v];
if(!gap){
visr[v]=1;
if(!lin[v]||dfs(lin[v])){
lin[v]=x;
return 1;
}
}
else l=min(l,gap);
}
return 0;
}
int main(){
int t;
cnt=0;
cin>>t;
while(t--){
cin>>n>>m;
int u,v,w,ans=0,tmp=0;
cnt=0;
me0(lin),me0(exr);
fill(exl+1,exl+n+1,-INF);
rep(i,1,n)
rep(j,1,n)
g[i][j]=-INF;
rep(i,1,m){
cin>>u>>v>>w;
g[u][v]=max(g[u][v],-w);
exl[u]=max(g[u][v],exl[u]);
}
rep(i,1,n){
while(1){
me0(visl),me0(visr);
if(dfs(i)) break;
rep(j,1,n){
if(visl[j]) exl[j]-=l;
if(visr[j]) exr[j]+=l;
}
}
}
rep(i,1,n)
ans+=g[lin[i]][i];
cout<<-ans<<endl;
}
return 0;
}
Work Scheduling
#include<iostream>
#include<cstring>
#include<queue>
#define mem(a,b) memset(a,b,sizeof a)
const int maxn=230;
int par[maxn],pre[maxn],link[maxn],n,ans;
std::deque<int> q;
std::vector<int> g[maxn]={};
char ty[maxn];
int findp(int x){return x==par[x]?x:par[x]=findp(par[x]);}
int Ti=0,times[maxn]={};
int lca(int x,int y){
for(Ti++;times[x]!=Ti;x^=y^=x^=y)
if(x) times[x]=Ti,x=findp(pre[link[x]]);
return x;
}
void blossom(int x,int y,int p){
while(findp(x)!=p){
pre[x]=y;
y=link[x];
par[x]=par[y]=p;
if(ty[y]==1) ty[y]=2,q.push_back(y);
x=pre[y];
}
}
bool Match(int x){
for(int i=0;i<=n;i++) ty[i]=0,par[i]=i;
q.clear();
ty[x]=2,q.push_back(x);
while(q.size()){
x=q.front(),q.pop_front();
for(int u:g[x])
if(ty[u]==0){
ty[u]=1;
pre[u]=x;
if(link[u]) q.push_back(link[u]),ty[link[u]]=2;
else {
for(;x;u=x){
x=link[pre[u]];
link[u]=pre[u];
link[link[u]]=u;
}
return 1;
}
}
else if(ty[u]==2&&findp(u)!=findp(x)){
int p=lca(x,u);
blossom(x,u,p),blossom(u,x,p);
}
}
return 0;
}
int main(){
mem(link,0);mem(pre,0);
ans=0;
scanf("%d",&n);
for(int f,t;~scanf("%d%d",&f,&t);){
g[f].push_back(t);
g[t].push_back(f);
}
for(int i=1;i<=n;i++)
if(!link[i]&&Match(i)) ans++;
printf("%d\n",ans*2);
for(int i=1;i<=n;i++) if(i<link[i])
printf("%d %d\n",i,link[i]);
}
Boke and Tsukkomi
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <cstdlib>
#define L(rt) (rt<<1)
#define R(rt) (rt<<1|1)
#define ll long long
using namespace std;
const int MAXN=50;
deque<int> Q;
bool g[MAXN][MAXN],inque[MAXN],inblossom[MAXN],vis[150];
int match[MAXN],pre[MAXN],base[MAXN];
int n,m,mmg;
vector<int>res;
struct node
{
int u,v;
}com[150];
int findancestor(int u,int v){
bool inpath[MAXN]={false};
while(1){
u=base[u];
inpath[u]=true;
if(match[u]==-1)break;
u=pre[match[u]];
}
while(1){
v=base[v];
if(inpath[v])return v;
v=pre[match[v]];
}
}
void reset(int u,int anc){
while(u!=anc){
int v=match[u];
inblossom[base[u]]=1;
inblossom[base[v]]=1;
v=pre[v];
if(base[v]!=anc)pre[v]=match[u];
u=v;
}
}
void contract(int u,int v,int n){
int anc=findancestor(u,v);
memset(inblossom,0,sizeof(inblossom));
reset(u,anc);reset(v,anc);
if(base[u]!=anc)pre[u]=v;
if(base[v]!=anc)pre[v]=u;
for(int i=1;i<=n;i++)
if(inblossom[base[i]]){
base[i]=anc;
if(!inque[i]){
Q.push_back(i);
inque[i]=1;
}
}
}
bool dfs(int S,int n){
for(int i=0;i<=n;i++)pre[i]=-1,inque[i]=0,base[i]=i;
Q.clear();Q.push_back(S);inque[S]=1;
while(!Q.empty()){
int u=Q.front();Q.pop_front();
for(int v=1;v<=n;v++){
if(g[u][v]&&base[v]!=base[u]&&match[u]!=v){
if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
else if(pre[v]==-1){
pre[v]=u;
if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
else{
u=v;
while(u!=-1){
v=pre[u];
int w=match[v];
match[u]=v;
match[v]=u;
u=w;
}
return true;
}
}
}
}
}
return false;
}
int MMG()
{
int ans=0;
memset(match,-1,sizeof(match));
for(int i=1;i<=n;i++)
if(match[i]==-1&&dfs(i,n)) ans++;
return ans;
}
int main()
{
int a,b;
while(~scanf("%d%d",&n,&m))
{
memset(g,false,sizeof(g));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
g[a][b]=g[b][a]=true;
com[i].u=a;
com[i].v=b;
}
mmg=MMG();
res.clear();
for(int i=1;i<=m;i++)
{
a=com[i].u;
b=com[i].v;
memset(g,false,sizeof(g));
for(int j=1;j<=m;j++)
if(j!=i)
{
int x=com[j].u,y=com[j].v;
if(x==a||x==b||y==a||y==b) continue;
g[x][y]=g[y][x]=true;
}
int t=MMG();
if(t!=mmg-1) res.push_back(i);
}
printf("%d\n",res.size());
if(res.size())
printf("%d",res[0]);
for(int i=1;i<res.size();i++)
printf(" %d",res[i]);
printf("\n");
}
return 0;
}