codeforces 241 E Flights

来源:互联网 发布:淘宝发错货的处理规定 编辑:程序博客网 时间:2024/06/11 02:42

题目大意

一个有向图,规定每条边的边权只能为1或2,要求给出一种方案,使得每条1到n的路径长度都一样。

题解

差分约束系统。
如果一条边不在1到n的路径上,那么就不用考虑它。
于是可以建出一个新图。
对于一条边(a,b),则有
dis(b)dis(a)2
dis(a)dib(b)1
然后跑一边SPFA,判掉负圈,有就是无解。
然后遍历所有的边,注意,只有在1~n的路径上的边,边权大于2或小于1时,才是无解,其他的边可以任意赋值,因为它们对答案无影响。
至于如何构图,我一开始是想dp一下,记录每个点是否可以到n。
我用-1表示未访问,1表示可以,0表示不可以
由于一些点不一定可以到达,所以这些点的dp值始终是-1,然而我在判断是不是在新图中时用的是dp[i]!=0,于是挂掉了,WA了好几次。
当然还可以两边dfs,从起点dfs一遍,终点在反向图上dfs一遍,两个点都可以到达的点才是新图上的点。
贴代码:
两边dfs:

#include <cstdio>#include <queue>#include <algorithm>using namespace std;const int M=1005;struct Edge{    int to,v,nxt;    Edge(int _to=0,int _v=0,int _nxt=0):to(_to),v(_v),nxt(_nxt){}}edge[M*10];int etot,n,m,a[M*10],b[M*10];queue<int>Q;int cnt[M],dis[M],head[M];bool mark[M],flag[M];void add_edge(int a,int b,int c){    edge[etot]=Edge(b,c,head[a]);    head[a]=etot++;}int on_the_road[M];bool SPFA(){    for(int i=2;i<=n;i++)        dis[i]=2000000000;    Q.push(1);    while(!Q.empty()){        int x=Q.front();        Q.pop();        mark[x]=0;        for(int i=head[x];~i;i=edge[i].nxt){            int to=edge[i].to;            if(on_the_road[to]!=2) continue;            if(dis[to]>dis[x]+edge[i].v){                dis[to]=dis[x]+edge[i].v;                if(++cnt[to]>n) return false;                if(!mark[to]){                    mark[to]=1;                    Q.push(to);                }            }        }    }    return true;}void dfs(int x,bool f){    if(flag[x]) return;    flag[x]=1;    on_the_road[x]++;    for(int i=head[x];~i;i=edge[i].nxt)        if((f==1)^(edge[i].v>0)) dfs(edge[i].to,f);}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        head[i]=-1;    for(int i=1;i<=m;i++){        scanf("%d%d",&a[i],&b[i]);        add_edge(a[i],b[i],2);        add_edge(b[i],a[i],-1);    }    dfs(1,0);    for(int i=1;i<=n;i++)        flag[i]=0;    dfs(n,1);    if(!SPFA()) puts("No");    else{        for(int j=1;j<=m;j++){            if(on_the_road[b[j]]==2&&on_the_road[a[j]]==2&&(dis[b[j]]-dis[a[j]]<=0||dis[b[j]]-dis[a[j]]>2)){                puts("No");                return 0;            }        }        puts("Yes");        for(int i=1;i<=m;i++){            if(dis[b[i]]-dis[a[i]]<1||dis[b[i]]-dis[a[i]]>2) puts("1");            else printf("%d\n",dis[b[i]]-dis[a[i]]);        }    }    return 0;}

dp

#include <cstdio>#include <queue>#include <algorithm>using namespace std;const int M=1005;struct Edge{    int to,v,nxt;    Edge(int _to=0,int _v=0,int _nxt=0):to(_to),v(_v),nxt(_nxt){}}edge[M*10];int etot,n,m,a[M*10],b[M*10];queue<int>Q;int cnt[M],dis[M],head[M];bool mark[M];void add_edge(int a,int b,int c){    edge[etot]=Edge(b,c,head[a]);    head[a]=etot++;}int on_the_road[M];bool SPFA(){    for(int i=2;i<=n;i++)        dis[i]=2000000000;    Q.push(1);    while(!Q.empty()){        int x=Q.front();        Q.pop();        mark[x]=0;        for(int i=head[x];~i;i=edge[i].nxt){            int to=edge[i].to;            if(!on_the_road[to]||on_the_road[to]==-1) continue;            if(dis[to]>dis[x]+edge[i].v){                dis[to]=dis[x]+edge[i].v;                if(++cnt[to]>n) return false;                if(!mark[to]){                    mark[to]=1;                    Q.push(to);                }            }        }    }    return true;}int dfs(int x){    if(on_the_road[x]!=-1) return on_the_road[x];    on_the_road[x]=0;    for(int i=head[x];~i;i=edge[i].nxt)        if(edge[i].v>0&&dfs(edge[i].to)) on_the_road[x]=1;    if(x==n) on_the_road[x]=1;    return on_the_road[x];}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        on_the_road[i]=head[i]=-1;    for(int i=1;i<=m;i++){        scanf("%d%d",&a[i],&b[i]);        add_edge(a[i],b[i],2);        add_edge(b[i],a[i],-1);    }    dfs(1);    if(!SPFA()) puts("No");    else{        for(int j=1;j<=m;j++){            if(on_the_road[b[j]]>0&&on_the_road[a[j]]>0&&(dis[b[j]]-dis[a[j]]<=0||dis[b[j]]-dis[a[j]]>2)){                puts("No");                return 0;            }        }        puts("Yes");        for(int i=1;i<=m;i++){            if(dis[b[i]]-dis[a[i]]<1||dis[b[i]]-dis[a[i]]>2) puts("1");            else printf("%d\n",dis[b[i]]-dis[a[i]]);        }    }    return 0;}
0 0
原创粉丝点击