最大流。
这东西好像叫三分图匹配。
源点向每个食物点连一条容量为1的边。
每个饮料点向汇点连一条容量为1的边。
将每个牛点拆点,食物点向喜欢它的牛的入点连一条容量为1的边,牛的出点向它喜欢的饮料点连一条容量为1的边。
最大流即为答案,每头牛拆点是为了保证每头牛只有一种食物和一种饮料。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 const int dian=505; 8 const int bian=50005; 9 const int INF=0x3f3f3f3f; 10 int h[dian],ver[bian],val[bian],nxt[bian],ch[dian],cr[dian]; 11 int n,m,k,tot,aa,bb,cc; 12 int S,T; 13 void add(int a,int b,int c){ 14 tot++;ver[tot]=b;val[tot]=c;nxt[tot]=h[a];h[a]=tot; 15 tot++;ver[tot]=a;val[tot]=0;nxt[tot]=h[b];h[b]=tot; 16 } 17 bool tell(){ 18 memset(ch,-1,sizeof(ch)); 19 queue<int>q; 20 q.push(S); 21 ch[S]=0; 22 while(!q.empty()){ 23 int t=q.front(); 24 q.pop(); 25 for(int i=h[t];i;i=nxt[i]) 26 if(ch[ver[i]]==-1&&val[i]){ 27 ch[ver[i]]=ch[t]+1; 28 q.push(ver[i]); 29 } 30 } 31 return ch[T]!=-1; 32 } 33 int zeng(int a,int b){ 34 if(a==T) 35 return b; 36 int r=0; 37 for(int i=cr[a];i&&b>r;i=nxt[i]) 38 if(ch[ver[i]]==ch[a]+1&&val[i]){ 39 int t=zeng(ver[i],min(b-r,val[i])); 40 val[i]-=t,r+=t,val[i^1]+=t; 41 if(val[i]) 42 cr[a]=i; 43 } 44 if(!r) 45 ch[a]=-1; 46 return r; 47 } 48 int dinic(){ 49 int r=0,t; 50 while(tell()){ 51 for(int i=1;i<=n+n+m+k+2;i++) 52 cr[i]=h[i]; 53 while(t=zeng(S,INF)) 54 r+=t; 55 } 56 return r; 57 } 58 int main(){ 59 memset(h,0,sizeof(h)); 60 memset(nxt,0,sizeof(nxt)); 61 tot=1; 62 scanf("%d%d%d",&n,&m,&k); 63 S=n+n+m+k+1,T=n+n+m+k+2; 64 for(int i=1;i<=m;i++) 65 add(S,i,1); 66 for(int i=1;i<=k;i++) 67 add(m+n+n+i,T,1); 68 for(int i=1;i<=n;i++) 69 add(m+i,m+n+i,1); 70 for(int i=1;i<=n;i++){ 71 scanf("%d%d",&aa,&bb); 72 for(int j=1;j<=aa;j++){ 73 scanf("%d",&cc); 74 add(cc,m+i,1); 75 } 76 for(int j=1;j<=bb;j++){ 77 scanf("%d",&cc); 78 add(m+n+i,m+n+n+cc,1); 79 } 80 } 81 printf("%d",dinic()); 82 return 0; 83 }
另,做这道题是因为今天考了一场试,网络流专题。
大爷看我们太弱没敢出太难,然后时间减了点,四个小时。
然后我脑残没打输入输出文件,爆零了。
赶紧打上,打上之后呢,还是爆零了。
其实就是一道都不会。
……
……
……
其实第一题不是很难,大概就是本题的加强版。
给一个n*m的矩形,有一些坏点,所有i行j列的非坏点,若i+j为偶数,则该点封印着一个恶魔。其他非坏点可以放置一个魔法水晶,魔法水晶能向且只能向相邻的一个点施法。对于一个恶魔,如果与它相邻的两个成直角的水晶同时向它施法,他就无法逃脱封印。问最多让多少恶魔无法逃脱封印。
1<=n,m<=50.
边想边写搞了两个小时,当我发现我的第六个建图是错的的时候,我就放弃了整场考试。
这题转化一下就是刚才的模型了。
考虑成直角的充要条件是左右中选一个,上下中选一个。所以就是对于一个恶魔点,总要选一个奇数行(列)的点和一个偶数行(列)的点。
这不就是食物和饮料嘛,源点连奇行点,偶行点连汇点,中间拆点然后相邻点连边,最大流完事。
主要就是要看出点间这种二分图关系。