雖然是裸題但是仍然沒有看出來......
1.每個人都對應一張床(可以的話),這樣把人和床看成點,對應關係就是邊,跑最大匹配看匹配數量夠不夠即可
2.連邊條件:如果一個學生且不回家,那麼他可以睡自己的床,向自己的床連邊
如果外來人且認識一個回家學生,那麼他可以睡學生的床,向學生的床連邊
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100; int T,n; struct node{ int v,nxt; }e[10000]; int head[maxn],cnt,tot,sum; int hom[maxn],sch[maxn]; int match[maxn]; bool v[maxn]; void add(int u,int v){ e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt; } bool dfs(int x){ for(int i=head[x];i;i=e[i].nxt){ int y=e[i].v; if(!v[y]){ v[y]=1; if(!match[y] || dfs(match[y])){match[y]=x;return 1;} } } return 0; } int main() { scanf("%d",&T); while(T--){ cnt=tot=sum=0; memset(head,0,sizeof(head)); memset(match,0,sizeof(match)); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&sch[i]); for(int i=1;i<=n;i++){ scanf("%d",&hom[i]); if(hom[i]==0 && sch[i])add(i,i);//在校不回家可以睡自己的床 } for(int i=1;i<=n;i++) if(!sch[i] || (sch[i] && !hom[i]))//需要床的人 tot++; for(int i=1,a;i<=n;i++) for(int j=1;j<=n;j++){ scanf("%d",&a);if(a && sch[j])add(i,j);//i認識j並且j是學生 } for(int i=1;i<=n;i++) if((sch[i] && hom[i]==0) || !sch[i]){//學生在學校或外來人 memset(v,0,sizeof(v)); if(dfs(i))sum++; } if(sum==tot)printf("^_^ "); else printf("T_T "); } }