阿里java笔试 附加题第二题
题目:
我们已经对客服进行了编号,第i(i>=1&&i<=n)个组的客服编号为2*i-1和2*i。并且知道了m种如下约束关系:客服编号a和客服编号b不能一起上班。
管理员需要聪明的你帮忙判断今天是否存在可行的方案,既满足m条约束关系,又能让每个组都有1个客服上班。
输入:n(代表有n个组)
m(m条约束关系),接下来会有m行
a,b(代表a,b两位客服标号不能同时上班)
阿里巴巴客服管理员管理着n个客服小组,他需要为每一组安排客服24小时值班。为简单起见,假设每组只有2个客服,一天只需要1个客服上班,并且一些客服由于某些原因不能在同一天上班。
我们已经对客服进行了编号,第i(i>=1&&i<=n)个组的客服编号为2*i-1和2*i。并且知道了m种如下约束关系:客服编号a和客服编号b不能一起上班。
管理员需要聪明的你帮忙判断今天是否存在可行的方案,既满足m条约束关系,又能让每个组都有1个客服上班。
输入:n(代表有n个组)
m(m条约束关系),接下来会有m行
a,b(代表a,b两位客服标号不能同时上班)
输出:判断有没有可行方案:如果不可行输出no;如果可行输出yes
非常典型的2-SAT模版题 如果有对SAT问题了解过应该一眼能看出
100%代码:
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
PrintWriter pw=new PrintWriter(System.out);
int n=sc.nextInt();
int m=sc.nextInt();
TwoSat t=new TwoSat();
t.init(n);
for(int i=0;i<m;i++){
String s=sc.nextLine();
String[] ss=s.split(",");
int a=Integer.valueOf(ss[0])-1;
int b=Integer.valueOf(ss[1])-1;
t.add_diredge(a,b^1);
t.add_diredge(b,a^1);
}
boolean k=t.solve();
if(k)pw.println("yes");
else pw.println("no");
pw.flush();
}
}
class TwoSat {
Edge[] edge;
int[] s,dfn,low,stack,belong;
int c;
int n;
boolean[] mark,instack;
//mark[i<<1]数组等于1,表示点i被选择
//mark[i<<1|1]数组等于1,表示点i没有被选择
int[] head;
int maxn = 2005; //注意是对数*2
int maxm = 4000005;
int[]to;
int[]next;
int cnt,bcount,dindex,top;
TwoSat() {
/*edge = new Edge[maxm];
for (int i = 0; i < maxm; ia`++)
edge[i] = new Edge();*/
to=new int[maxm];
next=new int[maxm];
head = new int[maxn];
s = new int[maxn];
mark = new boolean[maxn];
dfn=new int[maxn];
low=new int[maxn];
stack=new int[maxn];
belong=new int[maxn];
instack=new boolean[maxn];
}
void init(int n_) { //0~n*2
this.n = n_;
cnt = 0;
Arrays.fill(head, -1);
Arrays.fill(mark, false);
top=0;
bcount=0;
dindex=0;
Arrays.fill(dfn, 0);
}
boolean solve(){
for(int i=0;i<2*n;i++){
if(dfn[i]==0)tarjan(i);
}
for(int i=0;i<2*n;i+=2){
if(belong[i]==belong[i^1])return false;
}
return true;
}
void add_diredge(int u, int v) {
//edge[cnt].to = v;
//edge[cnt].next = head[u]; //感觉内存不够用下面的
to[cnt]=v;
next[cnt]=head[u];
head[u] = cnt++;
}
void tarjan(int u){
dfn[u]=low[u]=++dindex;
stack[++top]=u;
instack[u]=true;
// for(int i=head[u];i!=-1;i=edge[i].next){
for(int i=head[u];i!=-1;i=next[i]){
int v=to[i];
// int v=edge[i].to;
if(dfn[v]==0){
tarjan(v);
low[u]=Math.min(low[u], low[v]);
}else if(instack[v]&&dfn[v]<low[u]){
low[u]=dfn[v];
}
}
if(dfn[u]==low[u]){
bcount++;
int v;
do{
v=stack[top--];
instack[v]=false;
belong[v]=bcount;
}while(u!=v);
}
}
}
class Edge {
int to, next;
}
查看18道真题和解析
联想公司福利 1477人发布