[Poi2012]Festival

[Poi2012]Festival

时间限制: 1 Sec  内存限制: 64 MB

题目描述

有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}大小的最大值。

输入

第一行三个正整数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),表示第二类限制。

输出

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

如果无解输出NIE。

样例输入

4 2 2

1 2

3 4

1 4

3 1

样例输出

3

提示

|X3=1, X1=X4=2, X2=3

这样答案为3。容易发现没有更大的方案。

solution:

    这题一看就是差分约束,(然而我早忘了)。

         对于第一个条件,dis[a][b]=1,dis[b][a]=-1;对于第二个条件,dis[a][b]=min(dis[a][b],0);

     数据很小floyd就可以,如果存在负环即dis[i][i]<0无解,否则答案为每个环中的max-min+1(tarjan缩点)。

  

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 int read() {
  7     int s=0,f=1;
  8     char ch=getchar();
  9     while(ch>'9'||ch<'0') {
 10         if(ch=='-') {
 11             f=-1;
 12         }
 13         ch=getchar();
 14     }
 15     while(ch>='0'&&ch<='9') {
 16         s=(s<<1)+(s<<3)+(ch^48);
 17         ch=getchar();
 18     }
 19     return s*f;
 20 }
 21 int n,m1,m2;
 22 int dfn[601],low[601],tim,p,stack[601],cnt,belong[601],num[601];
 23 bool in[601];
 24 int dis[601][601],blo[601][601];
 25 void tarjan(int x) {
 26     dfn[x]=low[x]=++tim;
 27     stack[++p]=x;
 28     in[x]=true;
 29     for(int i=1; i<=n; ++i) {
 30         if(dis[x][i]!=1061109567) {
 31             if(dfn[i]==-1) {
 32                 tarjan(i);
 33                 low[x]=min(low[x],low[i]);
 34             } else {
 35                 if(in[i]) {
 36                     low[x]=min(low[x],dfn[i]);
 37                 }
 38             }
 39         }
 40     }
 41     if(dfn[x]==low[x]) {
 42         int y;
 43         ++cnt;
 44         do {
 45             y=stack[p--];
 46             in[y]=false;
 47             belong[y]=cnt;
 48             blo[cnt][++num[cnt]]=y;
 49         } while(x!=y);
 50     }
 51 }
 52 int main() {
 53     memset(dis,0x3f,sizeof(dis));
 54     memset(dfn,-1,sizeof(dfn));
 55     n=read(),m1=read(),m2=read();
 56     for(int i=1; i<=m1; ++i) {
 57         int x=read(),y=read();
 58         dis[x][y]=1;
 59         dis[y][x]=-1;
 60     }
 61     for(int i=1; i<=m2; ++i) {
 62         int x=read(),y=read();
 63         dis[y][x]=min(dis[y][x],0);
 64     }
 65     /*for(int i=1;i<=n;++i){
 66         for(int j=1;j<=n;++j){
 67             cout<<dis[i][j]<<" ";
 68         }
 69         cout<<endl;
 70     }*/
 71     for(int i=1; i<=n; ++i) {
 72         if(dfn[i]==-1) {
 73             tarjan(i);
 74         }
 75         dis[i][i]=0;
 76     }
 77     for(int k=1; k<=n; ++k) {
 78         for(int i=1; i<=n; ++i) {
 79             if(dis[i][k]!=1061109567) {
 80                 for(int j=1; j<=n; ++j) {
 81                     if(dis[i][j]>dis[i][k]+dis[k][j]) {
 82                         dis[i][j]=dis[i][k]+dis[k][j];
 83                     }
 84                 }
 85             }
 86         }
 87     }
 88     for(int i=1; i<=n; ++i) {
 89         if(dis[i][i]<0) {
 90             printf("NIE");
 91             return 0;
 92         }
 93     }
 94     int ans=0;
 95     for(int i=1; i<=cnt; ++i) {
 96         int sum=0;
 97         for(int j=1; j<=num[i]; ++j) {
 98             for(int k=1; k<=num[i]; ++k) {
 99                 sum=max(sum,dis[blo[i][j]][blo[i][k]]);
100             }
101         }
102         ans+=sum+1;
103     }
104     cout<<ans;
105     return 0;
106 }

 

 

 

posted @ 2017-08-14 21:35  Forever_goodboy  阅读(167)  评论(0编辑  收藏  举报