一本通P1519题解
【题意】: 根据宪法, 民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。
此委员会必须满足下列条件:
每个党派都在委员会中恰有 个代表,
如果 个代表彼此厌恶,则他们不能都属于委员会。
每个党在议会中有 个代表。代表从 编号到 。 编号为 和 的代表属于第 个党派。
任务:写一程序读入党派的数量和关系不友好的代表对,计算决定建立和平委员会是否可能,若行,则列出委员会的成员表。
【思路】:
算法的模板题。我们记
为
的队友,考虑如果
有矛盾,我们从
连一条边到
,从
连一条边到
。然后,直接跑一遍
算法,如果
和
属于同一个强联通分量,则输出NIE
,否则有解。
【代码】:
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
char c=0;int x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
const int N=16100,M=40100;
struct node{
int next,to;
}e[M];int h[N],tot;
inline void add(int a,int b){
e[++tot]=(node){h[a],b};h[a]=tot;
}
int dfscnt,dfn[N],low[N];
int Stack_top,Stack[N];
int belong[N],col,num[N];
void tarjan(int u){
dfn[u]=low[u]=++dfscnt;
Stack[++Stack_top]=u;
for(int i=h[u];i;i=e[i].next){
register int to=e[i].to;
if (dfn[to]==0){
tarjan(to);
low[u]=min(low[u],low[to]);
}
else if (!belong[to])
low[u]=min(low[u],dfn[to]);
}
if (low[u]==dfn[u]){
belong[u]=++col;num[col]=1;
while (Stack[Stack_top]!=u){
int v=Stack[Stack_top];
belong[v]=col;num[col]++;
--Stack_top;
}
--Stack_top;
}
}
int partner[N],n,m;
inline void read_the_data(){
n=read();m=read();
for(int i=1;i<=n;i++){
partner[i*2-1]=i*2;
partner[i*2]=i*2-1;
}
for(int i=1;i<=m;i++){
int u=read(),v=read();
add(u,partner[v]);
add(v,partner[u]);
}
}
inline void print_answer(){
for(int i=1;i<=n;i++)
if (belong[i*2]==belong[i*2-1]){
printf("NIE");
return;
}
for(int i=1;i<=2*n;i+=2)
if (belong[i]>belong[partner[i]])
printf("%d\n",partner[i]);
else printf("%d\n",i);
}
inline int hpwwzyy2012(){
read_the_data();
for(int i=1;i<=2*n;i++)
if (!dfn[i])
tarjan(i);
print_answer();
return 0;
}
int main(){
return hpwwzyy2012();
}
洛谷P3088
【题意】: 有 头奶牛沿着一维的栅栏吃草,第 头奶牛在目标点 ,它的身高是
当一头奶牛左边 距离内而且右边 距离内有身高至少是它的两倍的奶牛, ,它就会觉得拥挤。
请计算觉得拥挤的奶牛的数量。
【思路】: 首先,把牛按位置从小到大排序,然后进行计算。
考虑第
头牛是否感觉拥挤。如果奶牛感觉拥挤,代表
中牛的身高
,等同于
中最高的牛的身高
,所以我们可以用单调队列进行优化。
注意题目中说,左和右都要有至少有一头牛的身高
,所以分两部分,左和右,分别计算。当且仅当同时有解时,统计奶牛
进答案。
【代码】:
#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
char c=0;int x=0;bool f=0;
while (!g(c)) f=c=='-',c=gc;
while (g(c)) x=x*10+c-48,c=gc;
return f?-x:x;
}
const int N=50100;
struct node{
int location,height;
void read_itself(){
location=read();
height=read();
}
bool operator < (node c) const{
return location<c.location;
}
}a[N];int q[N],h,t,n,D;
int feel_crowded[N];
inline void read_the_date(){
n=read();D=read();
for(int i=1;i<=n;i++)
a[i].read_itself();
sort(a+1,a+n+1);
}
inline void calc_answer(){
h=1;t=0;q[1]=0;
for(int i=1;i<=n;i++){
while (h<=t&&a[q[h]].location<a[i].location-D) h++;
while (h<=t&&a[q[t]].height<=a[i].height) t--;q[++t]=i;
if (a[q[h]].height>=2*a[i].height) feel_crowded[i]++;
// printf("i=%d,h=%d,t=%d\n",i,h,t);
}
h=1;t=0;memset(q,0,sizeof(q));
// printf("------------\n");
for(int i=n;i;i--){
while (h<=t&&a[q[h]].location>a[i].location+D) h++;
while (h<=t&&a[q[t]].height<=a[i].height) t--;q[++t]=i;
if (a[q[h]].height>=2*a[i].height) feel_crowded[i]++;
// printf("i=%d,h=%d,t=%d\n",i,h,t);
}
}
inline void print_answer(){
register int ans=0;
for(int i=1;i<=n;i++)
if (feel_crowded[i]==2){
// printf("%d\n",i);
ans++;
}
printf("%d",ans);
}
inline int HPXXZYY(){
read_the_date();
calc_answer();
print_answer();
return 0;
}
int main(){
// freopen("t1.in","r",stdin);
return HPXXZYY();
}