一道需要考虑一下的匹配问题吧。
一开始自己看到这道题目,是想弄成二分图的形式,一边是猫,另一边是狗,但是这样建立每一组的关系有点复杂,并且不能套到二分图最大匹配的模型上。
后来再想了想,自己的方向有问题,应该是把人当作点,并根据人和人这件有没有矛盾关系来选择连不连边,这样这道题目就转化成了最大独立集的问题。
然后你跑一遍网络流,或者二分图匹配这题目就结束了。最大独立集=点数-最大匹配
#include "cstdio" #include "vector" #include "queue" #include "cstring" using namespace std; struct edge{int to,cap,rev;}; #define max_v 1111 #define inf 11111111 vector <edge> g[max_v]; int level[max_v]; int iter[max_v]; void add_edge(int from,int to,int cap){ g[from].push_back((edge){to,cap,(int)g[to].size()}); g[to].push_back((edge){from,0,(int)g[from].size()-1}); } void bfs(int s){ memset(level,-1,sizeof(level)); queue<int> que; level[s]=0; que.push(s); while(!que.empty()){ int v=que.front(); que.pop(); for(int i=0;i<g[v].size();i++){ edge &e=g[v][i]; if(e.cap>0&&level[e.to]<0){ level[e.to]=level[v]+1; que.push(e.to); } } } } int dfs(int v,int t,int f){ if(v==t) return f; for(int &i=iter[v];i<g[v].size();i++){ edge &e=g[v][i]; if(e.cap>0&&level[v]<level[e.to]){ int d=dfs(e.to,t,min(f,e.cap)); if(d>0){ e.cap-=d; g[e.to][e.rev].cap+=d; return d; } } } return 0; } int max_flow(int s,int t){ int flow=0; for(;;){ bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); int f; while((f=dfs(s,t,inf))>0){ flow+=f;} } } int main(){ int t; char s1[555][5],s2[555][5]; int c,d,v; scanf("%d",&t); while(t--){ scanf("%d%d%d",&c,&d,&v); memset(g,0,sizeof(g)); for(int i=1;i<=v;i++){ scanf("%s%s",s1[i],s2[i]); } for(int i=1;i<=v;i++){ for(int j=i+1;j<=v;j++){ if(strcmp(s1[i],s2[j])==0||strcmp(s2[i],s1[j])==0) { add_edge(i,j+v,1); add_edge(j,i+v,1); } } } for(int i=1;i<=v;i++) add_edge(0,i,1); for(int i=v+1;i<=2*v;i++) add_edge(i,2*v+1,1); printf("%d\n",v-max_flow(0,2*v+1)/2); } return 0; }
HDU 2768 Cat vs. Dog
最新推荐文章于 2021-10-27 10:10:05 发布