1. 程式人生 > >拓撲相關題目

拓撲相關題目

n個元素 有一個 計劃 div 技術分享 lose found logs true

有關拓撲一個挺直觀的圖:

技術分享

1.luogu P1347 排序

直通

思路:

  題目中明確的提到:確定n個元素的順序後即可結束程序,可以不用考慮確定順序之後出現矛盾的情況。

  所以我們可以每讀入一個條件,就進行一遍Floyd,判斷順序的條件就是:

    枚舉i,然後用map數組記錄一下比i要大的個數,如果n-sum==s+1(s+1的原因是因為我們是從0開始計數的),那麽就用一個q數組記錄下來

  而如果在給出的n之內,只要有一個沒有被確定,我們就不能夠說已經排好序了

  還有一點需要註意的是:

·    如果出現了map[i][i]=true的情況,則說明不合法,輸出"Inconsistency found after x relations.",其中的x就是我們輸入時所用到的i

坑點:

  別忘了輸出".",這個炒雞重要!

上代碼:

技術分享
#include <iostream>
#include <cstdio>
using namespace std;

const int E = 26;
const char a[E]={A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z};
int n,m;
char b[5];
int q[E];
bool map[E][E];

int floyd() { for(int k=0; k<n; k++) for(int i=0; i<n; i++) for(int j=0; j<n; j++) if(map[i][k] && map[k][j]) map[i][j]=true; for(int i=0; i<n; i++) if(map[i][i]) return 2; //不合法 for(int s=0; s<n; s++) { //枚舉順序
int sum,x=-1; for(int i=0; i<n; i++) { sum=0; //有幾個比i要大的 for(int j=0; j<n; j++) if(map[i][j]) sum++; if(n-sum==s+1) x=i; //匹配成功 } if(x==-1) return 0; //該位沒有被確定 q[s]=x; } return 1; } int main() { scanf("%d%d",&n,&m); for(int i=1,u,v; i<=m; i++) { scanf("%s",b); u=b[0]-A,v=b[2]-A; map[u][v]=true; int p=floyd(); if(p==1) { printf("Sorted sequence determined after %d relations: ",i); for(int i=0; i<n; i++) printf("%c",a[q[i]]);printf("."); return 0; } else if(p==2) { printf("Inconsistency found after %d relations.",i); return 0; } } printf("Sorted sequence cannot be determined."); return 0; }
View Code

2.luogu P1137 旅行計劃

直通

思路:

  用拓撲序列+dp來做

  轉移方程是 ans[v]=max(ans[v],ans[u]+1);(其中u的順序為拓撲的順序)

上代碼:

技術分享
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;

const int N = 100001;
const int M = 200001;
int n,m,u,v;
int ans[N];

struct node {
    int next,to;
}e[M];
int top,head[N];
void add(int u,int v) {
    top++;
    e[top].to=v;
    e[top].next=head[u];
    head[u]=top;
}

queue<int>q;
int ru[N],c[M];
void topo() {
    top=0;
    for(int i=1; i<=n; i++)
        if(!ru[i])
            q.push(i);
    while(!q.empty()) {
        u=q.front();
        q.pop();
        c[++top]=u;
        for(int i=head[u]; i; i=e[i].next) {
            v=e[i].to;
            ru[v]--;
            if(!ru[v]) q.push(v);
        }
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++) {
        scanf("%d%d",&u,&v);
        add(u,v);
        ru[v]++;
    }
    topo();
    for(int i=1; i<=n; i++) ans[i]=1;
    for(int x=1; x<=n; x++) {
        u=c[x];
        for(int i=head[u]; i; i=e[i].next) {
            v=e[i].to;
            ans[v]=max(ans[v],ans[u]+1);
        }
    }
    for(int i=1; i<=top; i++) printf("%d\n",ans[i]);
    return 0;
}
View Code

拓撲相關題目