zoukankan      html  css  js  c++  java
  • [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} ightarrow X_{a}-X_{b}=-1 ightarrow X_{a}-X_{b}geqslant -1(and)X_{a}-X_{b}leqslant -1$$

    而:

    $$X_{a}-X_{b}geqslant -1 ightarrow 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 ightarrow B$,权值为$W$的边,代表$A$要加上$W$才能到$B$

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

    第二种:

    $$X_{c}leqslant X_{d} ightarrow 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 }
    View Code
  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    http 请求code状态码
    js 跳转链接
    a标签-伪类
    在linux中如何解压.tgz
    dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.63.dylib
    nginx: [warn] conflicting server name "localhost" on 0.0.0.0:80, ignored
    微信小程序实现左滑删除效果(原生/uni-app)
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7356385.html
Copyright © 2011-2022 走看看