其他分享
首页 > 其他分享> > CF241E Flights 题解

CF241E Flights 题解

作者:互联网

CF241E

简要题意

\(n\) 个点,\(m\) 条有向边,每条边初始边权是 \(1\),让将一些边的边权变为 \(2\),使所有从点 \(1\) 到 \(n\) 的路径长度相等。

分析

首先发现如果一条边不在 \(1\) 到 \(n\) 的任意一条路径上,可以给它任意赋边权,因此只需考虑在 \(1\) 到 \(n\) 路径上的边。设 \(1\) 到 \(i\) 的最短路径长为 \(d_i\),由于所有 \(1\) 到 \(n\) 的路径都等长,于是有 \(\forall (u,v),d_u=d_v+w\),其中 \(w\) 为 \((u,v)\) 的边权。于是题目中对边权的限制可以转换为对 \(d\) 的限制,即:

\[\begin{cases} d_u-d_v\leq2 \\ 1\leq d_u-d_v \end{cases} \Longrightarrow \begin{cases} d_u\leq d_v+2\\ d_v\leq d_u+1 \end{cases} \]

,发现这是个典型的差分约束的形式,于是跑个 SPFA 就行了。最后 \((u,v)\) 的边权就是 \(d_v-d_u\)。

核心代码

int n,m,head[MAXN];vector<Pair>e;bitset<MAXN>v1,v2;
struct Edge{
    int to,dis,nxt;
    Edge(){;}Edge(int _to,int _dis,int _nxt):to(_to),dis(_dis),nxt(_nxt){}
};vector<Edge>edge;
void add_edge(int u,int v,int w){edge.push_back(Edge{v,w,head[u]});head[u]=edge.size()-1;}
int dis[MAXN],cnt[MAXN];bitset<MAXN>vis;queue<int>q;
bool spfa(int s){
    vis.reset();mem(dis,0x3f);mem(cnt,0);vis[s]=true;cnt[s]=1;dis[s]=0;q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u];i!=-1;i=edge[i].nxt){
            int v=edge[i].to,w=edge[i].dis;vis[u]=false;
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                if(!vis[v]) vis[v]=true,cnt[v]++,q.push(v);
                if(cnt[v]>=n) return false;
            }
        }
    }return true;
}vector<int>ed[MAXN];
void dfs(int u){
    for(auto v:ed[u]) if(!v1[v]) v1[v]=true,dfs(v);
}void dfs1(int u){
    for(auto v:ed[u]) if(!v2[v]) v2[v]=true,dfs1(v);
}
signed main(){
    qread(n,m);int i,j;mem(head,-1);
    for(i=1;i<=m;i++){
        int u,v;qread(u,v);e.push_back(Pair(u,v));
    }for(auto i:e) ed[i.first].push_back(i.second);
    dfs(1);for(i=1;i<=n;i++) ed[i].clear();
    for(auto i:e) ed[i.second].push_back(i.first);dfs1(n);
    if(!v1[n]) return printf("No\n"),0;v1[1]=v1[n]=v2[1]=v2[n]=true;
    for(auto i:e){
        if(v1[i.first]&&v1[i.second]&&v2[i.first]&&v2[i.second])
            add_edge(i.first,i.second,2),add_edge(i.second,i.first,-1);
    }
    if(!spfa(1)) return printf("No\n"),0;puts("Yes");
    for(auto i:e){
        if(v1[i.first]&&v1[i.second]&&v2[i.first]&&v2[i.second])
            printf("%lld\n",dis[i.second]-dis[i.first]);
        else printf("1\n",i.first,i.second);
    }
    #ifndef ONLINE_JUDGE
    system("pause > null");
    #endif
    return 0;
}

record

标签:cnt,int,题解,head,vis,Flights,edge,CF241E,dis
来源: https://www.cnblogs.com/lxy-2022/p/CF241E-Solution.html