m
约定 |
---|
1 | ≤10≤10 | n≤20n≤20,e≤25e≤25 | 2 | 3 | ≤100≤100 | e=nme=nm | 4 | 存在方案使得有 mm 个半空的筐子 | 5 | 不存在有半空的筐子的方案 | 6 | 7 | 无 | 8 | 9 | 10 |
时间限制:1s
空间限制:256MB256MB
思路&&分析:
这题其实首先我们先仔细想想,可以发现他是一个一般图最大匹配【不要想当然以为是二分图】。对于每个盒子,我们把它拆点拆成3个点,然后把这三个点两两连边(其实任选两个连一条边也行),然后对于每个条件,我们将这个球与属于这个框的三个点都连上边,之后用带花树跑个一般图最大匹配,答案就是Maxmatch−nMaxmatch−n(nn为球的个数)。(至于准确的证明,我还不会QAQ..)
Code
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
const int maxn=666,maxm=444444;
int n,m,que[maxm],ql,qr,pre[maxn],tim=0,h[maxn],tot=0,match[maxn],f[maxn],tp[maxn],tic[maxn],ecnt,T,res;
bool edge[maxn][maxn];
struct Edge {
int v,nxt;
}e[maxm];
inline int id(int x,int y) {
return n+(x-1)*3+y;
}
inline int find(int x) {
return f[x]==x?f[x]:f[x]=find(f[x]);
}
inline void add(int u,int v) {
e[++tot]=(Edge){v,h[u]};
h[u]=tot;
}
inline void addedge(int x,int y) {
add(x,y);
add(y,x);
}
inline int lca(int x,int y) {
for(++tim;;swap(x,y))
if(x) {
x=find(x);
if(tic[x]==tim)
return x;
tic[x]=tim,x=pre[match[x]];
}
}
inline void blossom(int x,int y,int p) {
while(find(x)!=p) {
pre[x]=y;
y=match[x];
if(tp[y]==2) {
tp[y]=1;
que[++qr]=y;
}
if(find(x)==x)
f[x]=p;
if(find(y)==y)
f[y]=p;
x=pre[y];
}
}
inline bool aug(int s) {
for(int i=1;i<=T;++i)
f[i]=i;
memset(tp,0,sizeof tp);
memset(pre,0,sizeof pre);
tp[que[ql=qr=1]=s]=1;
while(ql<=qr) {
int x=que[ql++];
for(int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {
if(find(v)==find(x)||tp[v]==2)
continue;
if(!tp[v]) {
tp[v]=2;
pre[v]=x;
if(!match[v]) {
for(int now=v,lst,tmp;now;now=lst) {
lst=match[tmp=pre[now]];
match[now]=tmp,match[tmp]=now;
}
return true;
}
tp[match[v]]=1;
que[++qr]=match[v];
}
else if(tp[v]==1) {
int l=lca(x,v);
blossom(x,v,l);
blossom(v,x,l);
}
}
}
return false;
}
int main() {
int Case;
read(Case);
while(Case--) {
tot=tim=0;
memset(h,0,sizeof h);
memset(match,0,sizeof match);
memset(tic,0,sizeof tic);
read(n);read(m);read(ecnt);
for(int i=1;i<=m;i++) {
addedge(id(i,1),id(i,2));
addedge(id(i,1),id(i,3));
addedge(id(i,2),id(i,3));
}
for(int i=1,x,y;i<=ecnt;++i) {
read(x),read(y);
addedge(id(y,1),x);
addedge(id(y,2),x);
addedge(id(y,3),x);
}
T=n+m*3,res=0;
for(int i=1;i<=T;i++)
res+=(!match[i]&&aug(i));
printf("%d\n",res-n);
for(int i=1;i<=n;i++)
printf("%d ",(match[i]-n-1)/3+1);
puts("");
}
return 0;
}
|