有n個人,編號為1~n,其中有m對朋友,現在給出m對朋友,問能不能把這n個人分成2個組,使得每一個組裡面的人都是互相不認識的?
若不可以,輸出No
若可以,問現在將認識的人兩兩配對,輸出最多可以有多少對
說白了,這道題就是首先要判斷是不是二分圖,不是的話輸出No,是的話輸出最大匹配
判斷二分圖:用黑白染色法,注意,整個關係圖有可能是不連通的,所以要遍歷所有的點
這裡求最大匹配不是用匈牙利算法,而是直接轉化為最大流
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 6 const int maxn=210; 7 const int inf=0x3f3f3f3f; 8 9 inline int min(int a,int b) 10 { 11 return a<b?a:b; 12 } 13 14 bool link[maxn][maxn]; 15 struct Edge 16 { 17 int to,next; 18 }; 19 Edge edge[maxn*maxn*2]; 20 int head[maxn]; 21 int tot; 22 bool flag; 23 int dye[maxn]; 24 int level[maxn]; 25 int iter[maxn]; 26 const int s=0; 27 int t; 28 29 void addedge(int u,int v) 30 { 31 edge[tot].to=v; 32 edge[tot].next=head[u]; 33 head[u]=tot++; 34 } 35 36 void init(int n) 37 { 38 memset(link,false,sizeof link); 39 memset(head,-1,sizeof head); 40 memset(dye,-1,sizeof dye); 41 tot=0; 42 flag=true; 43 } 44 45 void to_dye(int pre ,int u) 46 { 47 if(pre==-1) 48 dye[u]=1; 49 else 50 dye[u]=!dye[pre]; 51 52 for(int i=head[u];~i;i=edge[i].next) 53 { 54 int v=edge[i].to; 55 if(v==pre) 56 continue; 57 if(dye[v]!=-1) 58 { 59 if(dye[v]!=dye[u]) 60 continue; 61 else 62 { 63 flag=false; 64 } 65 } 66 else 67 to_dye(u,v); 68 } 69 } 70 71 struct Flow_Edge 72 { 73 int to,cap,rev; 74 }; 75 vector<Flow_Edge>flow_edge[maxn]; 76 77 void add(int from,int to,int cost) 78 { 79 flow_edge[from].push_back((Flow_Edge){to,cost,flow_edge[to].size()}); 80 flow_edge[to].push_back((Flow_Edge){from,0,flow_edge[from].size()-1}); 81 } 82 83 void build_graph(int n) 84 { 85 for(int i=0;i<=n;i++) 86 flow_edge[i].clear(); 87 88 t=n+1; 89 for(int i=1;i<=n;i++) 90 { 91 if(dye[i]==1) 92 add(s,i,1); 93 else 94 add(i,t,1); 95 } 96 for(int i=1;i<=n;i++) 97 { 98 for(int j=1;j<=n;j++) 99 { 100 if(i==j) 101 continue; 102 if(link[i][j]||link[j][i]) 103 { 104 if(dye[i]==1) 105 add(i,j,1); 106 else 107 add(j,i,1); 108 link[i][j]=false; 109 link[j][i]=false; 110 } 111 } 112 } 113 } 114 115 void bfs() 116 { 117 memset(level,-1,sizeof level); 118 queue<int>que; 119 while(!que.empty()) 120 que.pop(); 121 level[s]=1; 122 que.push(s); 123 while(!que.empty()) 124 { 125 int u=que.front(); 126 que.pop(); 127 for(int i=0;i<flow_edge[u].size();i++) 128 { 129 Flow_Edge &e=flow_edge[u][i]; 130 if(e.cap>0&&level[e.to]<0) 131 { 132 level[e.to]=level[u]+1; 133 que.push(e.to); 134 } 135 } 136 } 137 } 138 139 int dfs(int u,int f) 140 { 141 if(u==t) 142 return f; 143 for(int &i=iter[u];i<flow_edge[u].size();i++) 144 { 145 Flow_Edge &e=flow_edge[u][i]; 146 if(e.cap>0&&level[e.to]>level[u]) 147 { 148 int d=dfs(e.to,min(e.cap,f)); 149 if(d>0) 150 { 151 e.cap-=d; 152 flow_edge[e.to][e.rev].cap+=d; 153 return d; 154 } 155 } 156 } 157 return 0; 158 } 159 160 int max_flow(int n) 161 { 162 int flow=0; 163 while(1) 164 { 165 bfs(); 166 if(level[t]==-1) 167 return flow; 168 memset(iter,0,sizeof iter); 169 int f; 170 while(f=dfs(s,inf)) 171 { 172 if(f>0) 173 flow+=f; 174 } 175 } 176 } 177 178 int main() 179 { 180 int n,m; 181 while(~scanf("%d%d",&n,&m)) 182 { 183 init(n); 184 185 for(int i=0;i<m;i++) 186 { 187 int u,v; 188 scanf("%d%d",&u,&v); 189 link[u][v]=link[v][u]=true; 190 addedge(u,v); 191 addedge(v,u); 192 } 193 194 for(int i=1;i<=n;i++) 195 { 196 if(dye[i]==-1) 197 to_dye(-1,i); 198 } 199 200 //printf("eee\n"); 201 202 if(!flag) 203 { 204 printf("No\n"); 205 continue; 206 } 207 else 208 { 209 build_graph(n); 210 int flow=max_flow(n); 211 printf("%d\n",flow); 212 } 213 } 214 return 0; 215 }
时间: 2024-10-22 08:44:26