一本通P1519题解
【题意】: 根据宪法, B y t e l a n d Byteland Byteland 民主共和国的公众和平委员会应该在国会中通过立法程序来创立。 不幸的是,由于某些党派代表之间的不和睦而使得这件事存在障碍。
此委员会必须满足下列条件:
每个党派都在委员会中恰有 1 1 1 个代表,
如果 2 2 2 个代表彼此厌恶,则他们不能都属于委员会。
每个党在议会中有 2 2 2个代表。代表从 1 1 1 编号到 2 × n 2\times n 2×n。 编号为 2 × i − 1 2\times i−1 2×i−1 和 2 × i 2\times i 2×i 的代表属于第 i i i 个党派。
任务:写一程序读入党派的数量和关系不友好的代表对,计算决定建立和平委员会是否可能,若行,则列出委员会的成员表。
【思路】:
2
−
s
a
t
2-sat
2−sat算法的模板题。我们记
p
a
r
t
n
e
r
[
i
]
partner[i]
partner[i]为
i
i
i的队友,考虑如果
(
u
,
v
)
(u,v)
(u,v)有矛盾,我们从
u
u
u连一条边到
p
a
r
t
n
e
r
[
v
]
partner[v]
partner[v],从
v
v
v连一条边到
p
a
r
t
n
e
r
[
u
]
partner[u]
partner[u]。然后,直接跑一遍
t
a
r
j
a
n
tarjan
tarjan算法,如果
v
v
v和
p
a
r
t
n
e
r
[
v
]
partner[v]
partner[v]属于同一个强联通分量,则输出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
【题意】: F J FJ FJ有 N ( 1 ≤ N ≤ 50 , 000 ) N(1 \leq N \leq 50,000) N(1≤N≤50,000)头奶牛沿着一维的栅栏吃草,第 i i i头奶牛在目标点 x i x_i xi ,它的身高是 h i h_i hi ( 1 ≤ x i , h i ≤ 1 , 000 , 000 , 000 ) 。 (1 \leq x_i,h_i \leq 1,000,000,000)。 (1≤xi,hi≤1,000,000,000)。
当一头奶牛左边 D D D距离内而且右边 D D D距离内有身高至少是它的两倍的奶牛, ( 1 ≤ D ≤ 1 , 000 , 000 , 000 ) (1 \leq D \leq 1,000,000,000) (1≤D≤1,000,000,000),它就会觉得拥挤。
请计算觉得拥挤的奶牛的数量。
【思路】: 首先,把牛按位置从小到大排序,然后进行计算。
考虑第
i
i
i头牛是否感觉拥挤。如果奶牛感觉拥挤,代表
[
h
i
−
D
,
h
i
]
[h_i-D,h_i]
[hi−D,hi]中牛的身高
≥
2
×
x
i
\geq 2 \times x_i
≥2×xi,等同于
[
h
i
−
D
,
h
i
]
[h_i-D,h_i]
[hi−D,hi]中最高的牛的身高
≥
2
×
x
i
\geq 2 \times x_i
≥2×xi,所以我们可以用单调队列进行优化。
注意题目中说,左和右都要有至少有一头牛的身高
≥
2
×
x
i
\geq 2 \times x_i
≥2×xi,所以分两部分,左和右,分别计算。当且仅当同时有解时,统计奶牛
i
i
i进答案。
【代码】:
#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();
}