[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 }