CF1450E

差分约束板子。

因为相邻差绝对值为 $1$ ,所以有奇环一定无解。

$a_i+1=a_j$ 很好处理,关键在于 $|a_i-a_j|=1$ 。

对于 $|a_i-a_j|=1$ ,拆成两个条件: $a_i \leq a_j+1$和$a_i \geq a_j-1$ 。

枚举起点,特判有连边的点的最短路相等即可。

为什么呢?因为 $d_i=d_j$ 意味着起点到 $i$ 与 $j$ 距离相等, $i$ ,起点, $j$ 形成长度为偶数的路径,又因为 $i$ , $j$ 有边,所以存在奇环。

这题评2700原因应该是外国人不知道差分约束。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n,m,g[200][200];
int a[2000],b[2000],c;

int main(void)
{
    memset(g,0x3f,sizeof(g));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&a[i],&b[i],&c);
        g[a[i]-1][b[i]-1]=1;
        if(c==1) g[b[i]-1][a[i]-1]=-1;
        else g[b[i]-1][a[i]-1]=1;
    }
    for(int i=0;i<n;i++)
        g[i][i]=0;
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                g[j][k]=min(g[j][k],g[j][i]+g[i][k]);
    int pos=-1,ans=-1;
    for(int i=0;i<n;i++){
        if(g[i][i]<0){
            printf("NO\n");
            return 0;
        }
        int mx=-n,mn=n;
        for(int j=0;j<n;j++){
            mx=max(mx,g[i][j]);
            mn=min(mn,g[i][j]);
        }
        for(int j=0;j<m;j++)
            if(g[i][a[j]-1]==g[i][b[j]-1])
                mx=-n;
        if(ans<mx-mn){
            ans=mx-mn; pos=i;
        }
    }
    if(ans==-1) printf("NO\n");
    else{
        printf("YES\n%d\n",ans);
        for(int i=0;i<n;i++)
            printf("%d%c",g[pos][i]+n,i==n-1?'\n':' ');
    }
    return 0;
}
/*
*/
View Code

 

posted @ 2020-12-08 21:11  Miracle_Creater  阅读(131)  评论(0)    收藏  举报