Prefix Code
题目大意:
给出长度不超过十位的n个数字(有前缀0),判断其中是否存在一个数是其他数的前缀?
读题!读题读懂呀!
思路:
1、数据不是很大,所以直接暴力,把n个数字的所有前缀出现次数都统计出来,最后看有没有一个数字出现次数
≥
2
\geq 2
≥2即可。
但要注意用unordered_map,否则会TLE
2、用字典树查找前缀
暴力解法
#include<bits/stdc++.h>
using namespace std;
unordered_map<string,int>mp;
int main(){
int t;
cin>>t;
string s[10010];
for(int tt=1;tt<=t;tt++){
int n;
cin>>n;
mp.clear();
for(int i=0;i<n;i++){
cin>>s[i];
string a="";
for(int j=0;j<s[i].size();j++){
a+=s[i][j];
mp[a]++;//统计所有前缀的出现次数
}
}
int flag=0;
for(int i=0;i<n;i++){
if(mp[s[i]]>=2){//是否存在出现次数>=2的数字
flag=1;
break;
}
}
printf("Case #%d: ",tt);
if(flag) puts("No");
else puts("Yes");
}
return 0;
}
字典树解法
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;//开大一点,避免段错误
int tr[maxn][10];//第i个节点是否有j这个儿子
int vis[maxn],num[maxn];//统计数字的出现次数,统计前缀(包括数字本身)出现的次数
int cnt,flag;
void bt(string s){
int idx=0;
int len=s.size();
for(int i=0;i<len;i++){
int k=s[i]-'0';
if(!tr[idx][k]) tr[idx][k]=++cnt;
idx=tr[idx][k];
if(vis[idx]) flag=1;//当前数字的某个前缀与之前出现过的其他数字相同
num[idx]++;
}
if(num[idx]>=2){//当前数字出现次数超过两次,说明当前数字可以作为另一数字的前缀
flag=1;
}
vis[idx]=1;//标记当前数字
}
int main(){
int t;
cin>>t;
for(int tt=1;tt<=t;tt++){
//注意清空
memset(tr,0,sizeof(tr));
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(vis));
cnt=0,flag=0;
int n;
cin>>n;
for(int i=0;i<n;i++){
string s;
cin>>s;
bt(s);
}
printf("Case #%d: ",tt);
if(flag) puts("No");
else puts("Yes");
}
return 0;
}
Color Graph
题目大意:
给出n个点,m条边。现需删除一些边,使得图中不存在奇环,问图中最多能剩下多少条边。
思路:
关键点:目标图中不存在奇环(边数为奇数的环)。
二分图性质:
二分图中的所有环都是偶数长度,不存在奇数长度的环
无向图G为二分图的充分必要条件是,G至少有两个顶点,且其所有回路的长度均为偶数。
由于数据很小很小,所以暴力枚举,所有情况,取最大值即可。
dfs暴搜:n个点分到两个不同集合中的方法。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int u[maxn],v[maxn];
int vis[maxn];//标记为0和1,代表顶点被分到不同集合中
int n,m,ans;
void dfs(int x){
if(x==n+1){
int num=0;
for(int i=0;i<m;i++){
num+=vis[u[i]]^vis[v[i]];//原图中存在这样的边,一个顶点来着集合A,另一个顶底来着集合B
}
ans=max(ans,num);
return;
}
vis[x]=1;
dfs(x+1);
vis[x]=0;
dfs(x+1);
}
int main(){
int t;
cin>>t;
for(int tt=1;tt<=t;tt++){
cin>>n>>m;
for(int i=0;i<m;i++){
cin>>u[i]>>v[i];
}
ans=0;
memset(vis,0,sizeof(vis));
dfs(1);
printf("Case #%d: %d\n",tt,ans);
}
return 0;
}