Description
Solution
- 差分约束的裸题,太久没有做差分约束导致我完全忘记了这个东西。
- 首先如果有奇环显然不行,因此这是一个二分图。
-
a
u
=
a
v
+
1
a_u=a_v+1
au=av+1可以写成
a
u
≤
a
v
+
1
,
a
u
≥
a
v
+
1
a_u\le a_v+1,a_u\ge a_v+1
au≤av+1,au≥av+1。
-
∣
a
u
−
a
v
∣
=
1
|a_u-a_v|=1
∣au−av∣=1可以写成
a
v
−
1
≤
a
u
≤
a
v
+
1
a_v-1\le a_u \le a_v+1
av−1≤au≤av+1,又因为二分图的限制,一定可以满足上下界之一,所以不需要判断不相同的情况。
- floyd判负环——做完之后判断一下是否存在
d
i
s
u
,
u
<
0
dis_{u,u}<0
disu,u<0。
- 由于
a
u
−
a
v
≤
d
i
s
u
,
v
a_u-a_v\le dis_{u,v}
au−av≤disu,v,因此找到最大
d
i
s
u
,
v
dis_{u,v}
disu,v然后以
u
u
u作为起点即可
-
O
(
n
3
)
O(n^3)
O(n3)
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define maxn 205
#define maxm 2005
using namespace std;
int n,m,i,j,k,f[maxn][maxn],col[maxn],vis[maxn],ans,id;
void dfs(int x){
vis[x]=1;
for(int i=1;i<=n;i++) if (f[x][i]<=n){
if (!vis[i]) col[i]=col[x]^1,dfs(i); else
if (col[i]==col[x])
printf("NO\n"),exit(0);
}
}
int main(){
freopen("ceshi.in","r",stdin);
scanf("%d%d",&n,&m);
memset(f,127,sizeof(f));
for(i=1;i<=m;i++){
int x,y; scanf("%d%d%d",&x,&y,&k);
if (k) f[x][y]=1,f[y][x]=-1;
else f[x][y]=f[y][x]=1;
}
memset(vis,0,sizeof(vis));
dfs(1);
for(i=1;i<=n;i++) f[i][i]=0;
for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++)
if (f[i][k]<=1e9&&f[k][j]<=1e9)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
for(i=1;i<=n;i++) if (f[i][i]<0) printf("NO\n"),exit(0);
id=1;
for(i=1;i<=n;i++) for(j=1;j<=n;j++) if (abs(f[i][j])>ans)
ans=abs(f[i][j]),id=i;
printf("YES\n%d\n",ans);
for(i=1;i<=n;i++) printf("%d ",n+f[id][i]);
}