【A题】A. Stump Removal 链接click here~~
【题目大意】一排高低不平的树桩,需要用炸弹全部炸掉,如果一个树桩的前面和后面的树桩高度都比它小,炸弹爆炸的时候会同时炸掉,求尽可能少的放置炸弹的数目,输出树桩的编号。
【解题思路】 理解题意,从左往右扫,如果当前位置右边或左边的比它低了或相等,那么就把这个位置炸掉,然后把能炸的都炸掉,判断当前树桩前面的和后面的高度比较,
核心代码
for(int i=1;i<=n+1;i++)
{
if(a[i]>=a[i-1]&&a[i]>=a[i+1])
cout<<i<<endl;
}
【F题】F. Dollar Dayz BNU 14323
【题目大意】大数!求解钱币组合问题,坑题一道~~
代码:
/*
Author:HRW
大数!
*/
#include <string>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1001;
struct bign
{
int len,s[maxn];
bign()
{
memset(s,0,sizeof(s));
len = 1;
}
bign operator = (const char *num)
{
len = strlen(num);
for(int i=0; i<len; i++)s[i] = num[len-i-1] - '0';
return *this;
}
bign operator = (int num)
{
char s[maxn];
sprintf(s,"%d",num);
*this = s;
return *this;
}
bign(int num)
{
*this = num;
}
bign(const char *num)
{
*this = num ;
}
string str()const
{
string res = "";
for(int i=0; i<len; i++)
res = (char)(s[i] + '0') + res;
if (res == "")res = "0";
return res;
}
bign operator + (const bign& b)const
{
bign c;
c.len = 0;
for(int i=0,g = 0; g|| i<max(len,b.len); i++)
{
int x = g;
if(i<len) x+= s[i];
if(i<b.len) x+=b.s[i];
c.s[c.len++] = x%10;
g = x/10;
}
return c;
}
void clean()
{
while(len > 1 && !s[len-1]) len--;
}
bign operator += (const bign& b)
{
*this = *this + b;
return *this;
}
};
istream& operator >>(istream &in, bign& x)
{
string s;
in>>s;
x = s.c_str();
return in;
}
ostream& operator << (ostream &out, const bign& x)
{
out << x.str();
return out;
}
bign AC[1002];
int main()
{
int n,k;
while(cin>>n>>k)
{
AC[0] = 1;
for(int i=1; i<=k; i++)
for(int j=i; j<=n; j++)
AC[j]+=AC[j-i];
cout<<AC[n]<<endl;
}
return 0;
}
【E题】E. Redundant Paths BNU14319
【题目大意】给你一个连通的无向图G,至少要添加几条边,才能使其变为双连通图,和POJ 3177一样
【解题思路】一个有桥的连通图要变为双连通图的话,把双连通图收缩为一个点,形成一颗树,需要加的边为(L+1)/2,L为叶子节点个数
ps:BNU竟然加外挂会超时~~orz,以后还是得多注意。。
代码:
/*
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=5010;//点数
const int maxm=20100;//边数,无向
struct Edge
{
int to,next;
bool cut;//是否是桥标记
} edge[maxm];
int head[maxn],tot;
int Low[maxn],DFN[maxn],Stack[maxn],Belong[maxn];
int Index,top;
int block;//边双连通块数
bool instack[maxn];
int bridge;//桥的数目
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=head[u];
edge[tot].cut=false;
head[u]=tot++;
}
void Tarjan(int u,int pre)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
instack[u]=true;
for(int i=head[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(v == pre) continue;
if(!DFN[v])
{
Tarjan(v,u);
if(Low[u]>Low[v]) Low[u]=Low[v];
if(Low[v]>DFN[u])
{
bridge ++;
edge[i].cut = true;
edge[i^1].cut = true;
}
}
else if(instack[v]&&Low[u]>DFN[v])
Low[u]=DFN[v];
}
if(Low[u]==DFN[u])
{
block++;
do
{
v=Stack[--top];
instack[v]=false;
Belong[v]=block;
}
while(v!=u);
}
}
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
int du[maxn];//缩点后形成树,每个点的度数
void solve(int n)
{
memset(DFN,0,sizeof(DFN));
memset(instack,false,sizeof(instack));
Index=top=block=0;
Tarjan(1,0);
int res=0;
memset(du,0,sizeof(du));
for(int i=1; i<=n; i++)
for(int j=head[i]; j!=-1; j=edge[j].next)
if(edge[j].cut) du[Belong[i]]++;
for(int i=1; i<=block; i++)
if(du[i]==1)
res++;//找叶子节点个数为res,构造边双连通图需要加边(res+1)/2
printf("%d\n",(res+1)/2);
}
int shuru()
{
int sum=0;
char ch;
while((ch=getchar())<='0'||ch>='9');sum=ch-'0';
while((ch=getchar())>='0'&&ch<='9') sum=sum*10+ch-'0';
return sum;
}
int main()
{
//freopen("1.txt","r",stdin);
int n,m,u,v;
while(scanf("%d%d",&n,&m)==2)
{
init();
while(m--)
{
//scanf("%d%d",&u,&v);
u=shuru();
v=shuru();
addedge(u,v);
addedge(v,u);
}
solve(n);
}
return 0;
}