bzoj2788 festival 差分约束

填坑中……链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2788

题意:

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

首先看情况我们也知道是差分约束……

但是这个差分约束有些不一样在于这个东西会出环……所以我们要得出强连通分量……

得出来之后对于每个$SCC$分别考虑就行了……

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 using namespace std;
  6 const int maxn=605,maxm=200005;
  7 const int inf=0x3f3f3f3f;
  8 int n,m1,m2,cnt,tot,scnt;
  9 int head[maxn],MAP[maxn][maxn];
 10 int dfn[maxn],low[maxn],belong[maxn];
 11 struct node
 12 {
 13     int from,to,dis,next;
 14 }edge[maxm];
 15 void addedge(int u,int v,int w)
 16 {
 17     edge[++tot]=(node){u,v,w,head[u]};head[u]=tot;
 18 }
 19 #include<stack>
 20 stack<int>s;
 21 void tarjan(int root)
 22 {
 23     dfn[root]=low[root]=++cnt;s.push(root);
 24     for(int i=head[root];i;i=edge[i].next)
 25     {
 26         int v=edge[i].to;
 27         if(!dfn[v])
 28         {
 29             tarjan(v);
 30             low[root]=min(low[root],low[v]);
 31         }
 32         else if(!belong[v])low[root]=min(low[root],dfn[v]);
 33     }
 34     if(low[root]==dfn[root])
 35     {
 36         scnt++;int k;
 37         do
 38         {
 39             k=s.top();s.pop();
 40             belong[k]=scnt;
 41         }while(k!=root);
 42     }
 43 }
 44 int haha()
 45 {
 46     scanf("%d%d%d",&n,&m1,&m2);
 47     for(int i=1;i<=n;i++)
 48         for(int j=1;j<=n;j++)MAP[i][j]=-inf;
 49     for(int i=1;i<=n;i++)MAP[i][i]=0;
 50     for(int i=1;i<=m1;i++)
 51     {
 52         int x,y;scanf("%d%d",&x,&y);
 53         addedge(x,y,1),addedge(y,x,-1);
 54         MAP[x][y]=max(MAP[x][y],1);MAP[y][x]=max(MAP[y][x],-1);
 55     }
 56     for(int i=1;i<=m2;i++)
 57     {
 58         int x,y;scanf("%d%d",&x,&y);
 59         addedge(x,y,0);MAP[x][y]=max(MAP[x][y],0);
 60     }
 61     for(int i=1;i<=n;i++)
 62         if(!dfn[i])tarjan(i);
 63     int ans=0;
 64     for(int b=1;b<=scnt;b++)
 65     {
 66         int ret=0;
 67         for(int k=1;k<=n;k++)
 68         {
 69             if(belong[k]!=b)continue;
 70             for(int i=1;i<=n;i++)
 71             {
 72                 if(belong[i]!=b)continue;
 73                 if(MAP[i][k]==-inf)continue;
 74                 for(int j=1;j<=n;j++)
 75                 {
 76                     if(belong[j]!=b)continue;
 77                     if(MAP[k][j]==-inf)continue;
 78                     MAP[i][j]=max(MAP[i][j],MAP[i][k]+MAP[k][j]);
 79                 }
 80             }
 81         }
 82         for(int i=1;i<=n;i++)
 83         {
 84             if(belong[i]!=b)continue;
 85             for(int j=1;j<=n;j++)
 86             {
 87                 if(belong[j]!=b)continue;
 88                 ret=max(ret,abs(MAP[i][j]));
 89             }
 90         }
 91         ans+=ret+1;
 92     }
 93     for(int i=1;i<=n;i++)
 94         if(MAP[i][i])
 95         {
 96             puts("NIE");
 97             return 0;
 98         }
 99     printf("%d
",ans);
100 }
101 int sb=haha();
102 int main(){;}
bzoj2788
原文地址:https://www.cnblogs.com/Loser-of-Life/p/7351585.html