• [POI2012]Festival


    题目大意:
      有$n$个正整数$x_1,x_2,ldots,x_n$,再给出一些限制条件,限制条件分为两类:
        1.给出$A,B$,要求满足$X_A+1=X_B$;
        2.给出$C,D$,要求满足$X_Cleq X_D$。
      其中第1类限制条件有$m_1$个,第2类限制条件有$m_2$个。
      问这些限制条件是否能都被满足,如果能,求集合${x_i}$大小的最大值。

    思路:
      不难想到这是一个差分约束模型。
      对于第1类限制,连一条权值为$1$的边$A o B$,和一条权值为$-1$的边$B o A$。
      对于第2类限制,连一条权值为$0$的边$C o D$。
      这种连边方法很经典,难点在于连边以后如何求出集合大小的最大值。
      对于同一个SCC,我们只要跑一下最长路就可以唯一确定当前SCC的权值集合大小,因此我们可以先跑一遍Tarjan,然后Floyd求最长路。
      考虑不同SCC的关系。
      Tarjan缩完点以后就变成了一个DAG,且DAG上的边一定对应第2类限制(不然一定对称,就变成SCC了)。
      我们不妨假设不同SCC中的权值互不重叠,那么我们只需要将所有SCC的答案加起来即可。

      1 #include<stack>
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<vector>
      5 #include<algorithm>
      6 inline int getint() {
      7     register char ch;
      8     while(!isdigit(ch=getchar()));
      9     register int x=ch^'0';
     10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     11     return x; 
     12 }
     13 const int inf=0x7fffffff;
     14 const int N=601;
     15 struct Edge {
     16     int to,w;
     17 };
     18 bool ins[N];
     19 std::stack<int> s;
     20 std::vector<Edge> e[N];
     21 int dis[N][N],low[N],dfn[N],scc[N];
     22 inline void add_edge(const int &u,const int &v,const int &w) {
     23     e[u].push_back((Edge){v,w});
     24 }
     25 void tarjan(const int &x) {
     26     low[x]=dfn[x]=++dfn[0];
     27     s.push(x);
     28     ins[x]=true;
     29     for(unsigned i=0;i<e[x].size();i++) {
     30         const int &y=e[x][i].to;
     31         if(!dfn[y]) {
     32             tarjan(y);
     33             low[x]=std::min(low[x],low[y]);
     34         } else if(ins[y]) {
     35             low[x]=std::min(low[x],dfn[y]);
     36         }
     37     }
     38     if(low[x]==dfn[x]) {
     39         scc[0]++;
     40         int y=0;
     41         while(y!=x) {
     42             ins[y=s.top()]=false;
     43             s.pop();
     44             scc[y]=scc[0];
     45         }
     46     }
     47 }
     48 int main() {
     49     const int n=getint(),m1=getint(),m2=getint();
     50     for(register int i=1;i<=n;i++) {
     51         for(register int j=1;j<=n;j++) {
     52             if(i!=j) {
     53                 dis[i][j]=-inf;
     54             }
     55         }
     56     }
     57     for(register int i=0;i<m1;i++) {
     58         const int u=getint(),v=getint();
     59         add_edge(u,v,1);
     60         add_edge(v,u,-1);
     61         dis[u][v]=std::max(dis[u][v],1);
     62         dis[v][u]=std::max(dis[v][u],-1);
     63     }
     64     for(register int i=0;i<m2;i++) {
     65         const int u=getint(),v=getint();
     66         add_edge(u,v,0);
     67         dis[u][v]=std::max(dis[u][v],0);
     68     }
     69     for(register int i=1;i<=n;i++) {
     70         if(!dfn[i]) {
     71             tarjan(i);
     72         }
     73     }
     74     int ans=0;
     75     for(register int c=1;c<=scc[0];c++) {
     76         for(register int k=1;k<=n;k++) {
     77             if(scc[k]!=c) continue;
     78             for(register int i=1;i<=n;i++) {
     79                 if(scc[i]!=c||dis[i][k]==-inf) continue;
     80                 for(register int j=1;j<=n;j++) {
     81                     if(scc[j]!=c||dis[k][j]==-inf) continue;
     82                     dis[i][j]=std::max(dis[i][j],dis[i][k]+dis[k][j]);
     83                 }
     84             }
     85         }
     86         int tmp=0;
     87         for(register int i=1;i<=n;i++) {
     88             if(scc[i]!=c) continue;
     89             for(register int j=1;j<=n;j++) {
     90                 if(scc[j]!=c) continue;
     91                 tmp=std::max(tmp,std::abs(dis[i][j]));
     92             }
     93         }
     94         ans+=tmp+1;
     95     }
     96     for(register int i=1;i<=n;i++) {
     97         if(dis[i][i]) {
     98             puts("NIE");
     99             return 0;
    100         }
    101     }
    102     printf("%d
    ",ans);
    103     return 0;
    104 }
  • 相关阅读:
    SpringJMS解析2-JmsTemplate
    SpringJMS解析1-使用示例
    SpringHttpInvoker解析3-客户端实现
    算法笔记_084:蓝桥杯练习 11-1实现strcmp函数(Java)
    算法笔记_083:蓝桥杯练习 合并石子(Java)
    算法笔记_082:蓝桥杯练习 12-1三角形(Java)
    算法笔记_081:蓝桥杯练习 算法提高 矩阵乘法(Java)
    算法笔记_080:蓝桥杯练习 队列操作(Java)
    算法笔记_079:蓝桥杯练习 区间k大数查询(Java)
    算法笔记_078:蓝桥杯练习 最大最小公倍数(Java)
  • 原文地址:https://www.cnblogs.com/skylee03/p/8231272.html
Copyright © 2020-2023  润新知