Codeforces Global Round 12 E - Capitalism 差分约束+二分图判环

考虑怎么处理关系为0的状况

最开始写了一个分类讨论,然后发现这俩等式是矛盾的并不在一起,遂丢进垃圾箱里

但是,其实不关心谁大谁小,只要满足abs|Ai-Aj|==1就可以

根据解绝对值不等式的知识,解得:

-1<=Ai-Aj<=1

yeah,现在有不等式了,怎么处理最大化极差的问题?看到不等式想到跑差分约束,但是选最长路还是最短路?

假设有两个点u、v满足答案,即Au==maxAi,Av==minAi,i=0、1、2、3..且Au-Av是所有情况中最大的

一个性质:Au-Av<=dist(u,v)这里的dist指的是最短路

why最短路?粗略地想一下,假如v到u有多条路径,那肯定是由短板效应决定的。

否则如果取的是最长路径,那存在某条路径凑不出这么大呀!!

但是如果是最短路的话,最长路可以加加减减的凑出短的

Au-Av<=dist(u,v)    ->  max(Au,Av)<=max( dist(u,v) )

考虑到n只有200,所以可以枚举起点v,跑最短路得到dist数组,其中最大的即为解,然后不断更新即可

再从另一个观点理解:因为答案肯定来自某两点,枚举起点

根据差分约束的定义,得到的dist数组就是每个点的赋值

要最大化dist,也就是求差分约束最大解,见上一篇博客,应该跑最短路

最大解跑最短路,最小解跑最长路。

以上的前提是不存在奇环,可以先用二分图染色判一下。

所以做法就是二分图染色判奇环,然后跑n遍spfa跑差分约束(虽然正解是floyed呵呵呵

#include<bits/stdc++.h>
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int tot,n,m,l,r,k;
int a[maxn];
struct lys{
    int from,to,nex;
    ll val;
}e[int(1e6)];
int head[int(1e6)];
void add(int from,int to,ll val){
    tot++;e[tot].from=from;e[tot].to=to;
    e[tot].val=val;e[tot].nex=head[from];head[from]=tot;
}
int cnt[maxn];
bool vis[maxn];
ll dis[maxn];
bool spfa(int s)
{
    for(int i=1;i<=n;i++)   dis[i]=LONG_LONG_MAX,vis[i]=false,cnt[i]=0;
    dis[s]=0;
    deque<int> q;
    q.push_front(s);
    vis[s]=true;
    while(!q.empty())
    {
        int u;
        if(rand()&1)u=q.front(),q.pop_front();
        else u=q.back(),q.pop_back();
        vis[u]=false;
        for(int i=head[u];i;i=e[i].nex)
        {
            int v=e[i].to;ll w=e[i].val;
            if(dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                if(!vis[v])
                {
                    vis[v]=true;
                    cnt[v]++;
                    if(cnt[v]>=n+1) return false;
                     q.push_front(v);
                }
            }
        }
    }
    return true;
}
vector<int>g[maxn];
int col[maxn];
bool dfs(int v,int c){
    if(col[v]==c) return true;
    else if(col[v]==3-c) return false;
    else {
        col[v]=c;
        for(int i=0;i<g[v].size();i++){
            int to=g[v][i];
            if(dfs(to,3-c)==false) return false;
        }
        return true;
    }
}
int main()
{
    //freopen("lys.in","r",stdin);
    fastio;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        g[a].push_back(b);
        g[b].push_back(a);
        if(c==1){ // b-a>=1 b-a<=1
            add(a,b,1);
            add(b,a,-1);
        }
        else {
            //  equal    1>=a-b>=-1
            //  1>=a-b   b-a<=1
            add(a,b,1);
            add(b,a,1);
        }
    }
    bool valid=dfs(1,1);// 注意初始的颜色是1 
    if(valid==false){
        cout<<"NO";return 0;
    }
    ll ans=0,pos=0;
    for(int i=1;i<=n;i++){
        if(spfa(i)==true){
            ll maxn=0;
            for(int j=1;j<=n;j++){
               maxn=max(maxn,dis[j]);
            }
            if(maxn==LONG_LONG_MAX) continue;
            if(ans<=maxn) {
                ans=maxn;pos=i;
            }
        }
    }
    if(pos==0){
        cout<<"NO";
    }
    else {
        spfa(pos);
        cout<<"YES"<<endl;
        cout<<ans<<endl;
        for(int i=1;i<=n;i++) cout<<dis[i]<<" ";
    }
    return 0;
} 

 

posted @ 2023-02-10 21:40  liyishui  阅读(14)  评论(0编辑  收藏  举报