假期的宿舍
題目大意:
有n個人,分別是:在校的學生,回家的學生,來看望在校學生的學生,有人走了,就有空床,有人來了,就需要床,只能睡自己的床或者直接認識的人的床.
讀入有些煩,要仔細看:
第一行一個數 T 表示數據組數。接下來 T 組數據,每組數據第一行一個數n 表示涉及到的總人數。接下來一行 n 個數,第 i 個數表示第 i 個人是否是在校學生 (0 表示不是,1 表示是)。再接下來一行 n 個數,第 i 個數表示第 i 個人是否回家 (0 表示不回家,1 表示回家,注意如果第 i 個人不是在校學生,那么這個位置上的數是一個隨機的數,你應該在讀入以后忽略它)。接下來 n 行每行 n 個數,第 i 行第 j 個數表示 i 和 j 是否認識 (1 表示認識,0 表示不認識,第 i 行 i 個的值為 0,但是顯然自己還是可以睡自己的床),認識的關系是相互的。
解題思路:
話說這道題還挺難的.
在Codevs還是最高段位(大師)
可以用匈牙利算法,我用Dinic(網絡流——最大流)做的.
首先建立源點,匯點,源點連接需要床的人,匯點連接床,然后把人和他可以睡的床連接,再求最大流就可以了.
最重要的是初始化,因為是多組數據
源程序:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> #define inf 2147483647 using namespace std; int Q,n,m,s,t,cnt,last[2001],dis[2001],school[101],home[101],sum; struct node{int to,next,c;} e[2005]; queue<int> que;//隊列 void add(int u,int v,int c)//鄰接表 {e[cnt].to=v;e[cnt].c=c;e[cnt].next=last[u];last[u]=cnt++;e[cnt].to=u;e[cnt].c=0;e[cnt].next=last[v];last[v]=cnt++; } bool bfs()//bfs找增廣路,分層 {memset(dis,-1,sizeof(dis));//初始化while (!que.empty()) que.pop();//清空隊列dis[s]=0; que.push(s);//源點進入隊列while (!que.empty()){int u=que.front();que.pop();//把最先進入隊列的賦值給u然后出隊列for (int i=last[u];i!=-1;i=e[i].next)//找增廣路,分層if (e[i].c&&dis[e[i].to]==-1){dis[e[i].to]=dis[u]+1;if (e[i].to==t) return 1;//如果到了匯點就說明這是一條增光路唄que.push(e[i].to);//當然要進入隊列}}return 0; } int dfs(int x,int other) {if (x==t||!other) return other;int ret=0;//ret是已用流量,other是總共有的流量for (int i=last[x];i!=-1;i=e[i].next) //修改增廣路的流量if (e[i].c&&dis[e[i].to]==dis[x]+1){int f=dfs(e[i].to,min(e[i].c,other-ret));//接著改if (!f) dis[e[i].to]=-1;e[i].c-=f;e[i^1].c+=f;//改流量ret+=f;//改已用流量}if(!ret) dis[x]=-1;return ret; } int dinic(){int ans=0;while (bfs()) ans+=dfs(s,inf);//找增光路,改流量,計算答案return ans; } int main() {scanf("%d",&Q);for (int q=1;q<=Q;q++){scanf("%d",&n);cnt=0;memset(&e,0,sizeof(e));memset(last,-1,sizeof(last));s=n<<1|1; t=s+1; sum=0;//初始化for (int i=1;i<=n;i++){scanf("%d",&school[i]);if(school[i]) add(i+n,t,1);}//讀入,建邊for (int i=1;i<=n;i++){scanf("%d",&home[i]);if(!school[i]||!home[i]) add(s,i,1),sum++;}//讀入,建邊,sum統計需要床的人int flag;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++){scanf("%d",&flag);if(flag||i==j) add(i,j+n,1);//讀入關系,建邊}int ans=dinic();//賦值if (sum==ans) printf("^_^\n");else printf("T_T\n");//判定是否可以讓所有需要床的人都有床睡并輸出} }轉載于:https://www.cnblogs.com/Juruo-HJQ/p/9306899.html
總結
- 上一篇: 人工智能听了很多遍,都应用在哪些领域了你
- 下一篇: Oracle表