2/15 拓扑排序+dfs(规定方向的顺序很重要)+bfs

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2/15 拓扑排序+dfs(规定方向的顺序很重要)+bfs相关的知识,希望对你有一定的参考价值。

https://www.luogu.com.cn/problem/P1038
wa了一个点,当这个点的c[i]<=0时,是不能传递到下一层的

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e5+5;
int n,p,c[maxn],u,cnt,out[maxn],in[maxn],head[maxn];
bool vis[maxn],flag;
queue<int>q;
struct node

    int to,dis,nxt;
e[maxn];
void add(int from,int to,int w)

    e[++cnt].to=to;
    e[cnt].dis=w;
    e[cnt].nxt=head[from];
    head[from]=cnt;


int main()

    scanf("%d%d",&n,&p);
    for(int i=1;i<=n;i++)
    
        scanf("%d%d",&c[i],&u);
        if(c[i]>0)
            q.push(i);
        else
            c[i]-=u;
    
    for(int i=1;i<=p;i++)
    
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        out[u]++;
        in[v]++;
    
    while(!q.empty())
    
        int u=q.front();q.pop();
        if(c[u]<=0)
            continue;
        for(int i=head[u];i;i=e[i].nxt)
        
            int v=e[i].to;
            c[v]+=e[i].dis*c[u];
            in[v]--;
            if(!in[v])
                q.push(v);
        
    
    for(int i=1;i<=n;i++)
    
        if(!out[i]&&c[i]>0)
        
            printf("%d %d\\n",i,c[i]);
            flag=1;
        
    
    if(!flag)
        cout<<"NULL"<<endl;
    return 0;


一般的方法用queu的是求字典序最小的满足题目要求的拓扑序列
本题采用优先队列,反向建图,构造一个字典序最大的反向队列。
由于题目要求你把小的数尽量往前放,所以答案不一定是最小的字典序。但是,把小的数尽量往前放,那么大的数自然会尽量往后,这样一来,如果把拓扑序反过来,那么字典序最大的反拓扑序就一定是最优解。于是,我们可以建一个返图去求字典序最大的拓扑序,最后再倒序输出。 (引用)

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e5+5;
int n,m,p,c[maxn],u,cnt,in[maxn],head[maxn],ans[maxn],g;
bool vis[maxn],flag;
priority_queue<int>q;
struct node

    int to,nxt;
e[maxn];
void add(int from,int to)

    e[++cnt].to=to;
    e[cnt].nxt=head[from];
    head[from]=cnt;

void clean()

    memset(head,0,sizeof(head));
    memset(in,0,sizeof(in));
    memset(c,0,sizeof(c));
    memset(ans,0,sizeof(ans));
    cnt=0;g=0;
    while(!q.empty()) q.pop();

int main()

    int t;scanf("%d",&t);
    while(t--)
    
        clean();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        
            int u,v;scanf("%d%d",&u,&v);
            add(v,u);in[u]++;
        
        for(int i=1;i<=n;i++)
            if(!in[i]) q.push(i);
        while(!q.empty())
        
            int u=q.top();q.pop();
            ans[++g]=u;
            for(int i=head[u];i;i=e[i].nxt)
            
                int v=e[i].to;
                in[v]--;
                if(!in[v]) q.push(v);
            
        
        if(g<n)
            printf("Impossible!\\n");
        else
            for(int i=n;i>=1;i--)
            
                printf("%d ",ans[i]);
            
            cout<<endl;
            
    
    return 0;

P6145 [USACO20FEB]Timeline G
https://www.luogu.com.cn/problem/P6145
采用队列优化,将入读为0的点放到队列中
核定代码:a[v]=max(a[v],a[u]+e[i].dis); 这个结点最早在a[v]天完成,或者前驱节点+题中规定的几天

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e6+5;
struct node

    int to,dis,nxt;
e[maxn];
int a[maxn],head[maxn],in[maxn],cnt,n,m,c;
void add(int from,int to,int w)

    e[++cnt].to=to;
    e[cnt].dis=w;
    e[cnt].nxt=head[from];
    head[from]=cnt;

queue<int>q;

int main()

    scanf("%d%d%d",&n,&m,&c);
    for(int i=1;i<=n;i++)
    
        scanf("%d",&a[i]);
    
    for(int i=1;i<=c;i++)
    
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);in[v]++;
    
    for(int i=1;i<=n;i++)
        if(!in[i])
            q.push(i);
    while(!q.empty())
    
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].nxt)
        
            int v=e[i].to;
            a[v]=max(a[v],a[u]+e[i].dis);
            in[v]--;
            if(!in[v])
                q.push(v);
        
    
    for(int i=1;i<=n;i++)
        cout<<a[i]<<endl;
    return 0;

https://www.luogu.com.cn/record/69439301

#include <bits/stdc++.h>
#define y1 y11
using namespace std;
const int maxn=105;
const int inf=0x3f3f3f3f/2;
int n,mp[maxn][maxn],x1,y1,x2,y2,ans=inf;
int dx[4]=1,0,-1,0;
int dy[4]=0,-1,0,1;
bool flag;
void dfs(int x,int y,int dir,int k)

    if(k>=ans)
        return ;
    if(x==x2&&y==y2)
    
        ans=min(ans,k);flag=1;return ;
    
    for(int i=0;i<4;i++)
    
        int xx=x+dx[i],yy=y+dy[i];
        if(xx<=0||xx>n||yy<=0||yy>n)
            continue;
        if(!mp[xx][yy])
        
            mp[xx][yy]=-1;
            int d=0;
            if(dir!=i) d=1;     //方向不一样,就说明会转向,这个的循环0,1,2,3都代表一个方向
            if(dir==-1) d=0;   //处理方向的初始值
            dfs(xx,yy,i,k+d);
            mp[xx][yy]=0;
        
    

int main()

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    
        for(int j=1;j<=n;j++)
        
            char c;
            cin>>c;
            if(c=='A') x1=i,y1=j,mp[i][j]=1;
            else if(c=='B') x2=i,y2=j,mp[i][j]=0;
            else if(c=='x') mp[i][j]=-1;
        
    
    dfs(x1,y1,-1,0);
    if(flag)
        cout<<ans<<endl;
    else
        cout<<-1<<endl;
    return 0;


一道非常好的广搜题目。
https://www.luogu.com.cn/problem/P2049

#include <bits/stdc++.h>

using namespace std;
int m,n,k,mp[105][105],ans;
bool vis[105],used[105][105][105];
int dx[2]=1,0;
int dy[2]=0,1;
struct node

    int x,y,val;
;
queue<node>q;
void bfs()

    node cur,nxt;
    q.push(1,1,mp[1][1]);
    while(!q.empty())
    
        cur=q.front();q.pop();
        int x=cur.x,y=cur.y,w=cur.val;
        if(x==m&&y==n)
        
            vis[w]=1;
            continue;
        
        for(int i=0;i<2;i++)
        
            int nx=x+dx[i],ny=y+dy[i];
            int nw=(mp[nx][ny]*w)%k;
            if(nx<=0||nx>m||ny<=0||ny>n||used[nx][ny][nw])
                continue;
            q.push(nx,ny,nw);
            used[nx][ny][nw]=1;
        
    
    for(int i=0;i<k;i++)
    
        if(vis[i]) ans++;
    
    cout<<ans<<endl;
    for(int i=0;i<k;i++)
    
        if(vis[i]) cout<<i<<" ";
    
    cout<<endl;

int main()

    scanf("%d%d%d",&m,&n,&k);
    for(int i=1;i<=m;i++)
    
        for(int j=[AGC010E] Rearranging [拓扑排序+堆]

拓扑排序

拓扑排序(dfs)

Python中的拓扑排序算法(DFS)实现

逆拓扑排序实现思想以及通过DFS算法实现逆拓扑排序(C语言)

逆拓扑排序实现思想以及通过DFS算法实现逆拓扑排序(C语言)