zoukankan      html  css  js  c++  java
  • [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 && Xa+1>=Xb

    Xc<=Xd   ->   Xc-Xd<=0

    2.floyd判负环(无解)&&求出两点之间的最短距离

    初始化mp[i][j]为INF

    记录下边后,把mp[i][j]=0

    floyd一遍,如果mp[i][i]<0,说明存在负环   (因为自己到自己不是0,肯定是走了一个负环回来,变小了,一定有负环嘛)

    3.tarjan缩点

    最后的ans是所有强联通分量 max-min+1 的和

    证明:

    对于每一个强连通分量,把他们连起来的一定是  w=0  的边

    如果不是,一定是{1,-1},但是两个点之间的边是相反关系,如果有1/-1边连强连通分量,那么一定有一条-1/1的边

    就不是两个强连通分量了

    而又因为边只有{0,1,-1}的边,所以从最小值~最大值一定是连续的,min又一定是0,因为有1/-1的边

    所以ans=∑(max-min+1)

     

    对于每一个强连通分量,求出最短路的最大值+1,即为此强连通分量对ans的贡献

    累加起来即可

     

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #define mem(a,b) memset(a,b,sizeof(a))
      5 using namespace std;
      6 const int N=606;
      7 struct son
      8 {
      9     int v,next;
     10 };
     11 son a1[200066];
     12 int first[200066],e;
     13 void addbian(int u,int v)
     14 {
     15     a1[e].v=v;
     16     a1[e].next=first[u];
     17     first[u]=e++;
     18 }
     19 
     20 int n,m1,m2;
     21 int u,o;
     22 int mp[N][N];
     23 int dfn[N],low[N],now,ans;
     24 int zhan[200006],he,flag[N];
     25 int ji[N],jinow;
     26 
     27 void jilu()
     28 {
     29     int temp=-0x7fffffff;
     30     for(int i=1;i<=jinow;++i)
     31       for(int j=1;j<=jinow;++j)
     32       {
     33             if(mp[ji[i]][ji[j]]>temp)
     34               temp=mp[ji[i]][ji[j]];
     35         }
     36     ans+=temp+1;
     37 }
     38 
     39 void tarjan(int x)
     40 {
     41     //printf("x=%d
    ",x);
     42     low[x]=dfn[x]=++now;
     43     flag[x]=1;zhan[++he]=x;
     44     for(int i=first[x];i!=-1;i=a1[i].next)
     45     {
     46         int temp=a1[i].v;
     47         //cout<<temp;
     48         if(dfn[temp]==-1)
     49         {
     50             tarjan(temp);
     51             if(low[x]>low[temp])
     52               low[x]=low[temp];
     53         }
     54         else
     55           if(flag[temp])
     56             if(low[x]>dfn[temp])
     57               low[x]=dfn[temp];
     58     }
     59     
     60     if(low[x]==dfn[x])
     61     {
     62         int temp;
     63         jinow=0;
     64         while(1)
     65         {
     66             temp=zhan[he--];flag[temp]=0;
     67             ji[++jinow]=temp;
     68             if(temp==x)
     69               break;
     70         }
     71         jilu();
     72     }
     73 }
     74 
     75 int floyd()
     76 {
     77     int temp;
     78     for(int i=1;i<=n;++i)
     79       mp[i][i]=0;
     80     for(int k=1;k<=n;++k)
     81       for(int i=1;i<=n;++i)
     82         for(int j=1;j<=n;++j)
     83         {
     84                 temp=mp[i][k]+mp[k][j];
     85           if(mp[i][j]>temp)
     86             mp[i][j]=temp;
     87             }
     88     for(int i=1;i<=n;++i)
     89       if(mp[i][i]<0)
     90         return 0;
     91     return 1;
     92 }
     93 
     94 int main(){
     95     
     96     //freopen("1.txt","r",stdin);
     97     
     98     mem(first,-1);
     99     mem(mp,0x3f);
    100     mem(dfn,-1);
    101     
    102     scanf("%d%d%d",&n,&m1,&m2);
    103     for(int i=1;i<=m1;++i)
    104     {
    105         scanf("%d%d",&u,&o);
    106         addbian(u,o);
    107         addbian(o,u);
    108         mp[u][o]=min(1,mp[u][o]);
    109         mp[o][u]=min(-1,mp[o][u]);//有可能会重复 
    110     }
    111     for(int i=1;i<=m2;++i)
    112     {
    113         scanf("%d%d",&u,&o);
    114         addbian(o,u);
    115         mp[o][u]=min(0,mp[o][u]);
    116     }
    117     if(floyd()==0)
    118     {
    119         printf("NIE
    ");
    120         return 0;
    121     }
    122 //    cout<<0;
    123     for(int i=1;i<=n;++i)
    124       if(dfn[i]==-1)
    125         tarjan(i);
    126     
    127     cout<<ans<<endl;
    128     //while(1);
    129     return 0;
    130 }
    code

     

     

  • 相关阅读:
    MS SQL 错误 :17883,严重度: 1,状态: 0
    秒杀架构中高性能可扩展高可用的一点思考
    让IE10等支持classList2.0
    判定元素是否刚插入到DOM树
    accept巨坑
    for in 循环的输出顺序问题
    css斜线
    angular的directive笔记
    avalon最佳实践
    迷你MVVM框架 avalonjs 0.97发布
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7351610.html
Copyright © 2011-2022 走看看