1. 程式人生 > >C++ P1137 旅行計劃

C++ P1137 旅行計劃

題目描述

小明要去一個國家旅遊。這個國家有#NN個城市,編號為11至NN,並且有MM條道路連線著,小明準備從其中一個城市出發,並只往東走到城市i停止。

所以他就需要選擇最先到達的城市,並制定一條路線以城市i為終點,使得線路上除了第一個城市,每個城市都在路線前一個城市東面,並且滿足這個前提下還希望遊覽的城市儘量多。

現在,你只知道每一條道路所連線的兩個城市的相對位置關係,但並不知道所有城市具體的位置。現在對於所有的i,都需要你為小明制定一條路線,並求出以城市ii為終點最多能夠遊覽多少個城市。

輸入輸出格式

輸入格式:

第1行為兩個正整數N, M。

接下來M行,每行兩個正整數x, y,表示了有一條連線城市x與城市y的道路,保證了城市x在城市y西面。

輸出格式:

N行,第i行包含一個正整數,表示以第i個城市為終點最多能遊覽多少個城市。

輸入輸出樣例

輸入樣例:

5 6
1 2
1 3
2 3
2 4
3 4
2 5

輸出樣例:

1
2
3
4
3

題目連結:https://www.luogu.org/problemnew/show/P1137 


個人思路:

  • 因為小明的旅遊是有方向的,因此我們可以推出:如果存在一條路線為A->B,那麼B必然不能到A。因此,我們可以考慮拓撲排序
  • 由於拓撲排序的無後效性,這個題又要求在以 i 城市為終點的情況下,最多遊覽多少個城市。在上面我們談到了這個題的無後效性,因此我們可以寫一個關於最多遊覽數量的DP陣列。(在這個程式碼中,我使用了dp陣列)
  • dp方程:假設我們的遍歷是由u到v,則dp[v]=max(dp[u]+1,dp[v]).(之所以要用max是因為可能有其他城市連線v點)

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
int n,cnt=0,head[100005],dp[100005],rd[100005],cd[100005],sum[100005];
struct Edge{
    int v,w,nxt;
}e[200005];
int addEdge(int u,int v,int w){
    e[++cnt].v=v;
    e[cnt].w=w;
    e[cnt].nxt=head[u];
    head[u]=cnt;
}
void toposort(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        int nowRD=rd[i];
        if(nowRD==0){
            q.push(i);
        }
    }
    
    while(!q.empty()){
        int nowRD=q.front();q.pop();
        for(int i=head[nowRD];i;i=e[i].nxt){
            int v=e[i].v;
            rd[v]--;
            dp[v]=max(dp[nowRD]+1,dp[v]);
            if(rd[v]==0){
                q.push(v);
            }
        }
    }
}
int main(){
    int m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        addEdge(a,b,1);
        cd[a]++;//出度 
        rd[b]++;//入讀 
    }
    toposort();
    for(int i=1;i<=n;i++){
        printf("%d\n",dp[i]+1);
    }
    return 0;
}