题目大意:给定多组限制,限制分成2类,第一类是ax+1=ay 第二类是ax≤ay,求这些数最多有多少种不同的取值
首先一看就是差分约束,不妨先按照它建出来图,然后开始考虑如何取值
首先我们可以考虑环,假设图中出现了非0环,那么显然是无解的
而这个图中所有的强连通分量之间其实都是用“<=”连接的,他们是相互独立的
所以用tarjan求出所有强连通分量
对于每块强连通分量,由于是差分约束系统,两点之间的最短路代表他们取值最大差多少
所以把每块内部最长的最短路加起来就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#define N 200001
using namespace std;
int from[N],to[N],nxt[N],w[N],pre[N],cnt;
void ae(int ff,int tt,int ww)
{
cnt++;
from[cnt]=ff;
to[cnt]=tt;
w[cnt]=ww;
nxt[cnt]=pre[ff];
pre[ff]=cnt;
}
bool zai[N];
int dfn[N],low[N],b[N],cn,c;
int q[N],t;
void tarjan(int x)
{
cn++;
dfn[x]=low[x]=cn;
t++;q[t]=x;zai[x]=true;
int i,j;
for(i=pre[x];i;i=nxt[i])
{
j=to[i];
if(!dfn[j])
{
tarjan(j);
low[x]=min(low[x],low[j]);
}
else if(zai[j]) low[x]=min(low[x],dfn[j]);
}
if(low[x]==dfn[x])
{
c++;
while(q[t]!=x)
{
b[q[t]]=c;
zai[q[t]]=false;
t--;
}
b[q[t]]=c;
zai[q[t]]=false;
t--;
}
}
int f[601][601];
int main()
{
// freopen("fes.in","r",stdin);
// freopen("fes.out","w",stdout);
int n,m1,m2;
scanf("%d%d%d",&n,&m1,&m2);
int i,j;
int x,y;
for(i=1;i<=m1;i++)
{
scanf("%d%d",&x,&y);
ae(x,y,1);ae(y,x,-1);
}
for(i=1;i<=m2;i++)
{
scanf("%d%d",&x,&y);
ae(y,x,0);
}
for(i=1;i<=n;i++)
ae(0,i,0);
for(i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
memset(f,0x3f3f3f3f,sizeof(f));
for(i=1;i<=cnt;i++)
f[from[i]][to[i]]=min(f[from[i]][to[i]],w[i]);
for(i=1;i<=n;i++) f[i][i]=0;
int k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
f[i][j]=min(f[i][k]+f[k][j],f[i][j]);
int ans=0,maxn;
for(i=1;i<=n;i++)
if(f[i][i]<0)
{
puts("NIE");
return 0;
}
for(k=1;k<=c;k++)
{
maxn=0;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(b[i]==k&&b[j]==k)
maxn=max(maxn,f[i][j]);
ans+=maxn+1;
}
printf("%d\n",ans);
}