ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF241E Flights 题解

2022-09-16 20:04:00  阅读:272  来源: 互联网

标签:cnt int 题解 head vis Flights edge CF241E dis


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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有