1.cf26B Regular Bracket Sequence水题
题意:一串正反括号,去掉一些使剩下的序列合法并最长。
分析:一个栈即可解决问题。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
#define min(a,b) a<b?a:b
#define max(a,b) a<b?b:a
typedef unsigned long long ULL;
typedef long long LL;
using namespace std;
char str[1000005];
int main()
{
scanf("%s",str);
int len=0;
int now=0;
for(int i=0;i<strlen(str);i++)
{
if(str[i]==')'&&now==0)
continue;
if(str[i]=='(')
{
now++;
len++;
}
else
{
now--;
len++;
}
}
printf("%d\n",len-now);
return 0;
}
2.cf25C Roads in Berland
题意:有n个城市,每个城市都可到达其他任意城市并知道最短距离,先依次在两城市之间修建新的路,每修建一条路,输出此时所有对城市的距离之和。
分析:若在a,b间修建的新城市x小于原先d[a][b],根据floyed算法的思想,用两个for更新d,d[i][j]=min(d[i][j],d[i][a]+x+d[b][j]),d[i][j]=min(d[i][j],d[i][b]+x+d[a][j。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int,int> pii;
const int maxn=305;
int d[maxn][maxn];
int n,q;
int main()
{
scanf("%d",&n);
LL ans=0;
int a,b,w;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&d[i][j]);
ans+=d[i][j];
}
}
scanf("%d",&q);
for(int f=1;f<=q;f++)
{
scanf("%d%d%d",&a,&b,&w);
if(w<d[a][b])
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
d[i][j]=min(d[i][j],d[i][a]+w+d[b][j]);
d[i][j]=min(d[i][j],d[i][b]+w+d[a][j]);
}
}
ans=0;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
ans+=d[i][j];
if(f==q)
printf("%lld\n",ans);
else
printf("%lld ",ans);
}
return 0;
}
3.cf25D Roads not only in Berland 并查集
题意:有n个城市,n-1条路,现在要使所有城市都联通,但每修一条新路就要去掉一条现有路,输出修路数目,拆掉的路的两端点和新建的路的两端点。
分析:n-1条路恰好可以使所有城市联通,输入时用并查集判断不需要的路并记录,图被分为几个不连通的连通块,可用并查集找出每一个连通块的一个城市节点(父节点即可),问题就解决了。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
#define min(a,b) a<b?a:b
#define max(a,b) a<b?b:a
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=1005;
using namespace std;
int n;
int p[maxn];
int bian[maxn][2];
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
bool un(int i,int j)
{
int x=find(i);
int y=find(j);
if(x==y)
return false;
p[x]=y;
return true;
}
int main()
{
scanf("%d",&n);
int a,b;
int e=0;
int mm[maxn];
bool vis[maxn];
memset(vis,0,sizeof(vis));
int f=0;
for(int i=1;i<=n;i++)
p[i]=i;
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
if(!un(a,b))
{
bian[e][0]=a;
bian[e++][1]=b;
}
}
for(int i=1;i<=n;i++)
{
int op=find(i);
if(vis[op])
continue;
vis[op]=1;
mm[f++]=op;
}
printf("%d\n",e);
for(int i=0;i<e;i++)
{
printf("%d %d %d %d\n",bian[i][0],bian[i][1],mm[i],mm[i+1]);
}
return 0;
}
4.cf28B Party 数学题
题意:宴会上有n个人,没有朋友的走,在剩下的人里有一个朋友的走,在剩下的人里两个朋友的走.......,最后剩下最多多少人不用走。
分析:最好的情况是这样,n个人中,2个人互相不是朋友,这两个人与其余n-2个人都是朋友,则他们有n-2个朋友,其余n-2个人互相都是朋友,他们有n-1个朋友,2个n-2个朋友的先走,剩下的人从n-1个朋友变成了n-2个朋友,因此他们都不用走。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
#define min(a,b) a<b?a:b
#define max(a,b) a<b?b:a
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
using namespace std;
int main()
{
int t;
int n;
scanf("%d",&t);
for(int i=0;i<t;i++)
{
scanf("%d",&n);
if(n==1)
printf("0\n");
else
printf("%d\n",n-2);
}
return 0;
}
5.cf25E Test KMP
题意:3个字符串拼接成一个串,3个字符串都是这个字符串的字串,并使这个字符串最短。
分析:可枚举拼接顺序(只有6种,123,132,213,231,312,321),kmp见代码。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
#define min(a,b) a<b?a:b
#define max(a,b) a<b?b:a
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
using namespace std;
char s[3][maxn];
int next[3][maxn];
void get_next(int i)//构造next数组,next[i]存的是字符串下标0-(i-1)的相同前缀后缀最长长度
{
int len=strlen(s[i]);
int k=-1,j=0;
next[i][0]=-1;
while(j<len-1)
{
if(k==-1||s[i][k]==s[i][j])//匹配
{
k++;j++;
next[i][j]=k;
}
else
k=next[i][k];//不匹配,寻找更短的相同前缀后缀
}
}
int kmp(char* p,int f)
{
int len1=strlen(p);
int len2=strlen(s[f]);
int i=0,j=0;
while(i<len1&&j<len2)
{
if(j==-1||p[i]==s[f][j])
{
i++;
j++;
}
else
j=next[f][j];
}
return j;//若匹配成功,说明s[f]是p的字串,j==strlens[f];否则,
//j表示的是s[f]的前缀与p的后缀重合的字符数。
}
int solve(int i,int j,int k)
{
char str[maxn*3];
str[0]='\0';
int d=kmp(s[i],j);
strcat(str,s[i]);
strcat(str,s[j]+d);//拼接s[i]和s[j],除去公共部分
d=kmp(str,k);
strcat(str,s[k]+d);//拼接上s[k]
return strlen(str);
}
int main()
{
scanf("%s%s%s",s[0],s[1],s[2]);
for(int i=0;i<3;i++)
get_next(i);
int mi=inf;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
for(int k=0;k<3;k++)
if(i!=j&&j!=k&&i!=k)
mi=min(mi,solve(i,j,k));
cout<<mi<<endl;
return 0;
}