大意: 给一堆人的两两配对关系,让你把他们分两组(一个组中间不能有任何可以配对的),然后让两组之间可以配对的进行连线,问你最多有几个连线?
先判断是不是二分图: 节点染色,并且只用知道, 不是二分图的条件是:
某个点染为1,这个点下一个自然染 -1,可是却发现下个点的下一个点也被染成是-1 ,
出现某根线段两端点同色了
如果是二分图,直接套用匈牙利算法就行了。
第一步的染色和第二步使用匈牙利算最大匹配没任何关系
第一步只是为了判断 是不是 No
第二步利用链式前向星的天然优势 , 走一遍N个点的前向星,判断匹配个数
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class hdu2444 {
static int[] head, color,use,belong;
static int[][] map;
static int n,m,con;
static class e{
int u,v,next;
}static e[] es;
static void add(int u,int v) {
if(es[con]==null) es[con]=new e();
es[con].v=v;es[con].next=head[u];head[u]=con++;
}
//匈牙利算法前提,先判断是不是二分图
static int classify(int begin) { //二分类
Arrays.fill(color, -1);
Queue<Integer> q=new LinkedList<Integer>();
color[begin]=1;
q.add(begin);
while(!q.isEmpty()) {
int temp =q.poll();
for(int i=head[temp];i!=-1;i=es[i].next) {
int v= es[i].v;
if(color[v]==color[temp]) {
return -1;
}
if(color[v]==-1) {
color[v]=1-color[temp];
q.add(v);
}
}
}
return 1;
}
//
static int find(int a) {
for(int i=head[a]; i!=-1;i=es[i].next) {
int v=es[i].v;
if( use[v]==0) {
use[v]=1;
if(belong[v]==-1 || find(belong[v])==1) {
belong[v]=a;
return 1;
}
}
}
return 0;
}
static void init() {
Arrays.fill(head, -1);
Arrays.fill(belong, -1);
con=0;
}
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
color = new int[10010];
es=new e[40000];
head=new int[10010];
use =new int[10010];
belong =new int[10010];
while(sc.hasNext()) {
n=sc.nextInt();
m=sc.nextInt();
init();
for(int i=0;i<m;i++) {
int a =sc.nextInt();int b=sc.nextInt();
add(a, b);
}
if(classify(1)==-1) {
System.out.println("No");
continue;
}
int res=0;
for(int i=1;i<=n;i++) {
Arrays.fill(use, 0);
if(find(i)==1) {
res++;
}
}
System.out.println(res);
}
}
}