牛客链接
https://www.nowcoder.com/ta/huawei
素数伴侣 :【匈牙利算法:最大二分匹配】
二分图:将节点分成两组,A和B,边都是横跨在两组之间的,组内是没有边的相连的
判断方法,染色法
匹配:边的集合,任意两个边都没有公共的节点
最大匹配:找出匹配的边集合最大
交错路
增广路径
需要证明的是没有增广路径的时候就是最大匹配了
知乎一篇写的很不错的文章
https://zhuanlan.zhihu.com/p/96229700
看了这个算法,用了男女生匹配的方式进行讲解,其实match函数就是在找增广路径
增广路径要以没有匹配的节点开始,
所以match(i)的时候,i前面的要么是已经match了
要么就是考虑过了,没法match
如果match(i) 返回是真,那么就是说还存在增广路径
否则就是考虑到i的最大匹配了
正常来说,我们应该考虑所有的情况,最后挑一个最大的匹配
这里复杂度变低的原因就是,算法只从前到后运行一次
增广路径不可能往前找,满足贪心的性质,所以复杂度就低了
看懂题解之后 耗时23min
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define debug(x) cout<<#x<<": "<<(x)<<endl;
bool isp(int n){
int s = sqrt(n);
for(int i=2;i<=s;i++){
if(n%i==0){
return false;
}
}
return true;
}
int b[100];
int g[100];
bool l[100][100];
int v[100];
int bc;
int gc;
int p[100];
bool findg(int bi){
for(int gi=0;gi<gc;gi++){
if( l[bi][gi] && v[gi]==0){
v[gi] = 1;
if( p[gi]==-1 || findg( p[gi] ) ){
p[gi]=bi;
return true;
}
}
}
return false;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
bc = 0;
gc = 0;
fill(p,p+100,-1);
for(int i=0;i<n;i++){
int a=0;
scanf("%d",&a);
if(a%2==0){
b[bc++] = a;
}else{
g[gc++] = a;
}
}
for(int i=0;i<bc;i++){
for(int j=0;j<gc;j++){
l[i][j] = isp(b[i]+g[j]);
}
}
int cnt=0;
for(int i=0;i<bc;i++){
fill(v,v+100,0);
if(findg(i)){
cnt++;
}
}
cout<<cnt<<endl;
}
return 0;
}
HJ26 字符串排序
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
struct node{
char c;
int pos;
node(char c,int pos):c(c),pos(pos){}
};
int main(){
string str;
while(getline(cin,str)){
vector<node>a;
auto kind = [=](char c){
if(c>='A' && c<='Z'){
return 1;
}else if(c>='a' && c<='z'){
return 0;
}
return 2;
};
for(int i=0;i<str.size();++i){
if(kind(str[i])<2){
a.push_back(node{str[i],i});
}
}
auto cmp = [&](const node& x,const node& y){
int xk = x.c + kind(x.c)*32;
int yk = y.c + kind(y.c)*32;
if( xk == yk ){
return x.pos<y.pos;
}else{
return xk<yk;
}
};
sort(a.begin(),a.end(),cmp);
int k=0;
for(int i=0;i<str.size();++i){
if(kind(str[i])<2){
str[i] = a[k++].c;
}
}
cout<<str<<endl;
}
return 0;
}
HJ6 质数因子
描述
功能:输入一个正整数,按照从小到大的顺序输出它的所有质因子(重复的也要列举)(如180的质因子为2 2 3 3 5 )
数据范围:
输入描述:
输入一个整数
输出描述:
按照从小到大的顺序输出它的所有质数的因子,以空格隔开。最后一个数后面也要有空格。
示例1
输入:
180
复制
输出:
2 2 3 3 5
#include <iostream>
#include <cmath>
using namespace std;
using ll = long long;
int main(){
ll n;
cin>>n;
if(n==1){
cout<<1<<" ";
}
for(ll i=2;i<=sqrt(n);++i){
while(n>1){
if(n%i==0){
cout<<i<<" ";
n/=i;
}else{
break;
}
}
}
if(n>1){
cout<<n<<" " ;
}
cout<<endl;
return 0;
}
HJ74 参数解析
在命令行输入如下命令:
xcopy /s c:\\ d:\\e,
各个参数如下:
参数1:命令字xcopy
参数2:字符串/s
参数3:字符串c:\\
参数4: 字符串d:\\e
请编写一个参数解析程序,实现将命令行各个参数解析出来。
解析规则:
1.参数分隔符为空格
2.对于用""包含起来的参数,如果中间有空格,不能解析为多个参数。比如在命令行输入xcopy /s "C:\\program files" "d:\"时,参数仍然是4个,第3个参数应该是字符串C:\\program files,而不是C:\\program,注意输出参数时,需要将""去掉,引号不存在嵌套情况。
3.参数不定长
4.输入由用例保证,不会出现不符合要求的输入
数据范围:字符串长度:
进阶:时间复杂度:,空间复杂度:
输入描述:
输入一行字符串,可以有空格
输出描述:
输出参数个数,分解后的参数,每个参数都独占一行
示例1
输入:
xcopy /s c:\\ d:\\e
复制
输出:
4
xcopy
/s
c:\\
d:\\e
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main(){
string s;
getline(cin,s);
int i=0;
int n = s.size();
int yc=0;
vector<string>r;
for(i=0;i<n;){
if(s[i]==' '){
++i;
continue;
}else if(s[i]=='"'){
++i;
int j = s.find('"',i);
if(j==-1){
break;
}
r.push_back(s.substr(i,j-i));
i = j+2;
}else{
int j = s.find(' ',i);
if(j==-1){
break;
}
r.push_back(s.substr(i,j-i));
i = j+1;
}
}
if(i<n){
r.push_back(s.substr(i));
}
cout<<r.size()<<endl;
for(auto ss:r){
if(ss[0]=='"'){
cout<<ss.substr(1,ss.size()-2)<<endl;
}else{
cout<<ss<<endl;
}
}
return 0;
}