[Poi2012]Festival

[Poi2012]Festival

题目

有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类:

1. 给出a,b (1<=a,b<=n),要求满足Xa + 1 = Xb

2. 给出c,d (1<=c,d<=n),要求满足Xc <= Xd

在满足所有限制的条件下,求集合{Xi}大小的最大值。

INPUT

第一行三个正整数n, m1, m2 (2<=n<=600, 1<=m1+m2<=100,000)。

接下来m1行每行两个正整数a,b (1<=a,b<=n),表示第一类限制。

接下来m2行每行两个正整数c,d (1<=c,d<=n),表示第二类限制。

OUTPUT

一个正整数,表示集合{Xi}大小的最大值。

如果无解输出NIE。

SAMPLE

INPUT

4 2 2

1 2

3 4

1 4

3 1

OUTPUT

3

解题报告

显然是一道差分约束

首先,我们来分析一下两种限制条件:

第一种:

$$X_{a}+1=X_{b} \rightarrow X_{a}-X_{b}=-1\rightarrow X_{a}-X_{b}\geqslant -1(and)X_{a}-X_{b}\leqslant -1$$

而:

$$X_{a}-X_{b}\geqslant -1\rightarrow X_{b}-X_{a}\leqslant 1$$

也就是:

$$X_{a}-X_{b}\leqslant -1(and)X_{b}-X_{a}\leqslant 1$$

对于这种限制条件,我们需要从$X_{a}$向$X_{b}$建一条权值为$1$的边,向$X_{b}$向$X_{a}$建一条权值为$-1$的边。

想想为什么?

我们可以这样理解差分约束中两点的边:一条从$A\rightarrow B$,权值为$W$的边,代表$A$要加上$W$才能到$B$

这样就可以解释上面的建边原理了

第二种:

$$X_{c}\leqslant X_{d}\rightarrow X_{c}-X_{d}\leqslant 0$$

对于这种限制条件,我们需要从$X_{d}$向$X_{c}$建一条权值为$0$的边。

建完了图,我们首先要判断是否有解,也就是是否存在负环,我们可以这样做:

先将每个$dis[i][i]$赋值为$0$,然后$FLoyd$跑最短路,然后判断$dis[i][i]$(也就是自己到自己)是否为负

为什么这样做?

我们先想$Floyd$的原理,它是不断枚举两点之间的中间点进行松弛操作,对在点$i$和$j$之间的所有其他点进行一次松弛。那么,我们想,假如没有负环的话,$dis[i][i]$应当是$0$才对,但是,显然负权边的权值小于$0$,也就是说,在松弛的过程中,负权边会松弛$dis[i][i]$,假如形成了负环,那么,必然会有负环上的点的$dis[i][i]$被该负环松弛成了负值,所以这种做法是正确的

然后,我们就该处理答案了

我们先tarjan缩个点,找到一圈强连通分量,我们想,对于每一个强连通分量,把他们连起来的一定是$w=0$的边,假如是$1or-1$的边,那么,一定存在反向的$-1or1$的边将他们反向相连,使他们互相连通,那么,这两个强连通分量就成了一个强连通分量

我们想,我们建的边的权值只有$-1$,$0$,$1$三种,那么,由这三种边连起来的数一定是连续的数

也就是说,我们的强连通分量的最小值$min$到最大值$max$是连续的,且$min$一定是$0$

所以我们对于每一个强连通分量对答案的贡献就是:

$$max-min+1$$

想想为什么?

我们考虑一串连续的自然数,比如说$1$到$9$,我们有$9$个数,这$9$个数是如何得到的呢?

由等差数列求项数公式可以得到:

$$num=\frac{a_{n}-a_{1}}{d}+1$$

其中$num$为项数,$a_{n}$为末项,$a_{1}$为首项,$d$为公差。

然后,又因为$min$为0,所以每一个强连通分量对答案的贡献为:

$$max+1$$

对每一个强连通分量的贡献求和即为答案

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 inline int read(){
 6     int sum(0);
 7     char ch(getchar());
 8     for(;ch<‘0‘||ch>‘9‘;ch=getchar());
 9     for(;ch>=‘0‘&&ch<=‘9‘;sum=sum*10+(ch^48),ch=getchar());
10     return sum;
11 }
12 struct edge{
13     int e;
14     edge *n;
15     edge():e(0),n(NULL){}
16 }a[200005],*pre[605];
17 int tot;
18 inline void insert(int s,int e){
19     a[++tot].e=e;
20     a[tot].n=pre[s];
21     pre[s]=&a[tot];
22 }
23 int n,m1,m2;
24 int g[605][605];
25 inline bool fly(){
26     for(int i=1;i<=n;++i)
27         g[i][i]=0;
28     for(int k=1;k<=n;++k)
29         for(int i=1;i<=n;++i)
30             for(int j=1;j<=n;++j)
31                 if(g[i][k]+g[k][j]<g[i][j])
32                     g[i][j]=g[i][k]+g[k][j];
33     for(int i=1;i<=n;++i)
34         if(g[i][i]<0)
35             return false;
36     return true;
37 }
38 int dfn[605],low[605],sta[605],zhan[605];
39 int top,head;
40 bool vis[605];
41 int cnt;
42 int ans(0);
43 inline void tarjan(int u){
44     dfn[u]=low[u]=++cnt;
45     sta[++top]=u;
46     vis[u]=1;
47     for(edge *i=pre[u];i;i=i->n){
48         int e(i->e);
49         if(!dfn[e]){
50             tarjan(e);
51             low[u]=min(low[u],low[e]);
52         }
53         else
54             if(vis[e])
55                 low[u]=min(low[u],dfn[e]);
56     }
57     if(low[u]==dfn[u]){
58         head=0;
59         int tmp;
60         while(1){
61             zhan[++head]=tmp=sta[top--];
62             vis[tmp]=0;
63             if(tmp==u)
64                 break;
65         }
66         tmp=-0x7fffffff;
67         for(int i=1;i<=head;++i)
68             for(int j=1;j<=head;++j)
69                 tmp=max(tmp,g[zhan[i]][zhan[j]]);
70         ans+=tmp+1;
71     }
72 }
73 int main(){
74     memset(pre,NULL,sizeof(pre));
75     memset(g,0x3f,sizeof(g));
76     n=read(),m1=read(),m2=read();
77     for(int i=1;i<=m1;++i){
78         int x(read()),y(read());
79         insert(x,y),insert(y,x);
80         g[x][y]=min(g[x][y],1),g[y][x]=min(g[y][x],-1);
81     }
82     for(int i=1;i<=m2;++i){
83         int x(read()),y(read());
84         insert(y,x);
85         g[y][x]=min(g[y][x],0);
86     }
87     if(!fly()){
88         puts("NIE");
89         return 0;
90     }
91     for(int i=1;i<=n;++i)
92         if(!dfn[i])
93             tarjan(i);
94     printf("%d",ans);
95 }

时间: 2024-10-06 05:33:53

[Poi2012]Festival的相关文章

[BZOJ2788][Poi2012]Festival

2788: [Poi2012]Festival Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 187  Solved: 91[Submit][Status][Discuss] Description 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: 1. 给出a,b (1<=a,b<=n),要求满足Xa + 1 = Xb 2. 给出c,d (1<=c,d<=n),要求满足Xc <= Xd 在满足所

[Poi2012]Festival 变态 差分约束题

题意 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: 1. 给出a,b (1<=a,b<=n),要求满足Xa + 1 = Xb 2. 给出c,d (1<=c,d<=n),要求满足Xc <= Xd 在满足所有限制的条件下,求集合{Xi}大小的最大值. (自己注:求集合中不相同的的元素最多) solution (最后发现我tarjan写挂了......) 1.建图 Xa+1==Xb   ->   Xa+1<=Xb &&

Bzoj 2789: [Poi2012]Letters 树状数组,逆序对

2789: [Poi2012]Letters Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 278  Solved: 185[Submit][Status][Discuss] Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. Input 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度

[BZOJ2797][Poi2012]Squarks

2797: [Poi2012]Squarks Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 211  Solved: 89[Submit][Status][Discuss] Description 设有n个互不相同的正整数{X1,X2,...Xn},任取两个Xi,Xj(i≠j),能算出Xi+Xj.现在所有取法共n*(n-1)/2个和,要你求出X1,X2,...Xn. Input 第一行一个正整数n (3<=n<=300).第二行n*(n-1)/2

hdu 1850 Being a Good Boy in Spring Festival (尼姆博弈)

Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4658    Accepted Submission(s): 2781 Problem Description 一年在外 父母时刻牵挂春节回家 你能做几天好孩子吗寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场悄悄给爸爸买

HDU - 1850 - Being a Good Boy in Spring Festival

先上题目: Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4557    Accepted Submission(s): 2713 Problem Description 一年在外 父母时刻牵挂春节回家 你能做几天好孩子吗寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场

HDU 1850 Being a Good Boy in Spring Festival 博弈

Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7841    Accepted Submission(s): 4811 Problem Description 一年在外 父母时刻牵挂春节回家 你能做几天好孩子吗寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场悄悄给爸爸买

Being a Good Boy in Spring Festival(尼姆博弈)

Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 51 Accepted Submission(s): 45   Problem Description 一年在外 父母时刻牵挂春节回家 你能做几天好孩子吗寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场悄悄给爸爸买个小礼物主动地

[BZOJ2791][Poi2012]Rendezvous

2791: [Poi2012]Rendezvous Time Limit: 25 Sec  Memory Limit: 128 MBSubmit: 95  Solved: 71[Submit][Status][Discuss] Description 给定一个n个顶点的有向图,每个顶点有且仅有一条出边.对于顶点i,记它的出边为(i, a[i]).再给出q组询问,每组询问由两个顶点a.b组成,要求输出满足下面条件的x.y:1. 从顶点a沿着出边走x步和从顶点b沿着出边走y步后到达的顶点相同.2.