前言
资本主义终将被社会主义取代!
题目
讲解
其实吧这道题如果能想到差分约束就基本搞定了。
- (b=1),(a_u+1=a_v),那么我们可以看做 (a_u+1ge a_v) 和 (a_u+1le a_v)。
- (b=0),(|a_u-a_v|=1),我们可以看做 (a_u+1ge a_v) 或 (a_v+1ge a_u)。
连边跑最短路,如果存在负环即无解。由于是多源最短路,这里我们采用 ( t Floyd) 算法。
之后我们要求极差最大,枚举起点算极差即可。值得注意的是有连边的点权值不能相等,如果相等,那么此情况应舍去。
那么可能会有人问了,你上面的条件是不等式,你只用判断相等就可以判断无解吗?
是的,因为如果连边,两个点的权值差一定相差为 (1),如果为 (0),即为不合法,应该舍去。
最后值得注意的是因为求出来的最短路可能有负数,输出的时候随便加个大一点的正数使其变为正数即可。
代码
int dis[MAXN][MAXN];
void Add_Edge(int x,int y,int z){dis[x][y] = Min(dis[x][y],z);}
bool check()
{
for(int k = 1;k <= n;++ k)
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n;++ j)
dis[i][j] = Min(dis[i][j],dis[i][k]+dis[k][j]);
for(int i = 1;i <= n;++ i) if(dis[i][i] < 0) return 0;
return 1;
}
pair<int,int> e[MAXM];
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = Read(); m = Read();
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n;++ j)
if(i ^ j) dis[i][j] = INF;
else dis[i][j] = 0;
for(int i = 1;i <= m;++ i)
{
int u = Read(),v = Read(),w = Read();
Add_Edge(u,v,1);
if(w) Add_Edge(v,u,-1);//au+1 = av
else Add_Edge(v,u,1);//|au - av| = 1
e[i] = make_pair(u,v);
}
if(!check()) {printf("NO
");return 0;}
int ret = -1,jc = -1;
for(int u = 1;u <= n;++ u)
{
bool fk = 1;
for(int i = 1;i <= m && fk;++ i)
if(dis[u][e[i].first] == dis[u][e[i].second])
fk = 0;
if(!fk) continue;
int MAX = -INF,MIN = INF;
for(int v = 1;v <= n;++ v)
{
MAX = Max(MAX,dis[u][v]);
MIN = Min(MIN,dis[u][v]);
}
if(jc < MAX - MIN) jc = MAX-MIN,ret = u;
}
if(ret < 0) {printf("NO
");return 0;}
printf("YES
");
Put(jc,'
');
for(int i = 1;i <= n;++ i) Put(dis[ret][i]+100000,' ');
return 0;
}