可以想到是个二分图,x节点是喜欢狗的,y节点是喜欢猫的,在有冲突的节点间连边(x节点间不会有冲突,y节点间不会有冲突,所以是二分图),即若x[ i ]喜欢的是y[ j ]讨厌的,或x[ i ]讨厌的是y[ j ]喜欢的,那么g[ i ][ j ] = g[ j ][ i ] = 1,则该二分图的最大点独立集除以2就是所求,除以2的原因是求了两次。
#include <stdio.h> #include <string.h> #define maxn 510 int nx,ny; int g[maxn][maxn],ans,sx[maxn],sy[maxn]; int cx[maxn],cy[maxn]; int path(int u) { sx[u]=1; int v; for(v=1;v<=ny;v++) { if(g[u][v]>0&&!sy[v]) { sy[v]=1; if(!cy[v]||path(cy[v])) { cx[u]=v;cy[v]=u; return 1; } } } return 0; } void solve() { ans=0; int i; memset(cx,0,sizeof(cx)); memset(cy,0,sizeof(cy)); for(i=1;i<=nx;i++) { if(!cx[i]) { memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); ans+=path(i); } } } struct Node { int l; int d; }node[maxn]; int main() { int i,j; int n;//cat int m;//dog int p; while(scanf("%d%d%d",&n,&m,&p)!=EOF) { memset(g,0,sizeof(g)); char d; int id; for(i=1;i<=p;i++) { getchar(); scanf("%c%d",&d,&id); if(d=='D') node[i].l=id; else if(d=='C') node[i].l=m+id; getchar(); scanf("%c%d",&d,&id); if(d=='D') node[i].d=id; else if(d=='C') node[i].d=m+id; } for(i=1;i<=p;i++) for(j=1;j<=p;j++) { if(i==j) continue; if(node[i].l==node[j].d||node[i].d==node[j].l) g[i][j]=g[j][i]=1; } nx=ny=p; solve(); printf("%d ",(2*p-ans)/2); } return 0; }