第七屆Code+程序設計全國挑戰賽 normal T1 最小路徑串


題目描述

n 個點 m 條邊的無向圖中,所有點用從 0 開始的 6 位數字串編號,即 000000000001000002、……直到 \(n−1\) 對應的 6 位數字串。保證 \(n≤1e6\),所以 6 位的編號不會溢出。

對於除了 000000 以外的每個點,你需要找到一條從 000000 出發且不經過重復點的路徑,使得路徑上所有點的數字串順次連接形成的串的字典序最小。

比較兩個不同的串的字典序的方法是:如果其中某個串是另一個的前綴,則較短的串字典序較小;否則,找出兩個串從左往右掃描時遇到的首個不相等的位置,在這個位置上的數字較小的串字典序較小。

由於輸出路徑過於麻煩,你不需要完整地輸出路徑,只需要將路徑上所有點的數字串視作一個整數,輸出這個數對 998244353 取模的結果。

輸入格式

從標准輸入讀入數據。

第一行輸入兩個整數 \(n\)\(m\)

第二行輸入一個長度為 \(12m\) 的數字串,依次表示每條邊。每條邊用 12 個數字表示,其中前 6 個與后 6 個數字分別表示這條邊所連接的兩個點的編號。

注意,輸入中可能會包含自環或重邊。

輸出格式

輸出到標准輸出。

輸出 n−1 行,依次輸出除了點 000000 本身以外,點 000000 到每個點的字典序最小的路徑,視為整數后對 998244353 取模的結果。

如果點 000000 不可到達某個點,則在對應的行改為輸出 -1。

樣例1輸入

5 5
000000000003000001000003000001000002000002000000000002000003

樣例1輸出

2000001
2
517560944
-1

樣例1解釋

000000000001 所求的路徑對應的串為 000000000002000001
000000000002 所求的路徑對應的串為 000000000002
000000000003 所求的路徑對應的串為 000000000002000001000003,對 998244353 取模后為 517560944
000000000004 不存在路徑。

子任務

子任務1(11分)
\(1≤n≤1e6,m=0\)

子任務2(55分)

\(1≤n≤10,0≤m≤20\)

子任務3(34分)

\(1≤n≤1e6,0≤m≤1e6\)

剛開始拿到這道題的時候還有點暈,首先我們可以否定直接吧路徑字符串存下來,我們可以把字符串轉化成數來存儲。但是我們就無法比較兩條路徑的字典序先后,但我們又可以發現,一條路徑最優,當且僅當它的每一個路徑上的數都是最小,但不一定是最短,則我們有以下dfs代碼:

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxs=1e7+2e6+100,maxn=1e6+50;
typedef long long ll;
const ll mod=998244353;
vector<int> e[maxn];
int n,m;
char s[maxs];
ll ans[maxn];

inline bool cmp(const int &a,const int &b) {return a<b;}

void dfs(int u,ll dis)
{
    ans[u]=dis;
    int siz=e[u].size();
    for(int i=0;i<siz;i++)
        if(ans[e[u][i]]==-1) dfs(e[u][i],(dis*1000000+e[u][i])%mod);
}

int main()
{
    int u,v;
    scanf("%d%d%s",&n,&m,s);
    memset(ans,-1,sizeof(ans));
    for(int i=1;i<=m;i++)
    {
        u=v=0;
        for(int j=(i-1)*12;j<i*12-6;j++)
            u=(u<<1)+(u<<3)+(s[j]^48);
        for(int j=i*12-6;j<i*12;j++)
            v=(v<<1)+(v<<3)+(s[j]^48);
        if(u==v) continue;
        e[u].push_back(v);e[v].push_back(u);
    }
    for(int i=0;i<n;i++) sort(e[i].begin(),e[i].end(),cmp);
    dfs(0,0);
    for(int i=1;i<n;i++) printf("%lld\n",ans[i]);
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM