@codeforces - コアラ@ 1209Fとノートブック


@説明@

M nは接続された無向図エッジの所与の点、1、2、...、Mの順に応じて、入力番号の各エッジ。
今、数側の番号の後にビューの一点は、私は、私はそれを書き留めます。ライトの数との間に隙間がないため、そうすべての数は、最終的に番号に接続される書き留めます。
1以外の各点について、それがエンドポイントとして使用される場合、最終的に最小数にどのくらいですか?
応答モード出力10 ^ 9 + 7。あなたが出力する必要があることに注意してください可能な最小数の残りの部分を、とすべきではない可能な最小の残りの部分

入力
最初の行は、2つの整数nとm(^ 52≤n≤10、N-含有 1≤m≤10^ 5)、 それは点とエッジの数を表します。
二つの整数Xi及びYIの次のm行は、iがエッジにコネクション物品XI、YIを表します。
ノー重い側面ことを確実にするために。図は、通信を確保します。

出力
出力N - 1数桁、i番目のI + 1数^ 9 + 7 MOD 10の可能な最小数の終点を示しています。

実施例の
入力
11 10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
出力
1
12
123
1234
12345
123456
1234567
12345678
123456789
345678826

@解決@

最初のエッジUを考える- >重量は小数として表される多桁V I、ある場合(_10 \(D1 ... DM))\、エッジをmに分割することができるが、U - > A1(D1) 、A1 - > A2(D2) 、...、AM-1 - > V(DM)。
これは、以下の便利な操作を有する、エッジの重みのそれぞれは、0から9に変更されることができます。

2進数、最初の数字の比較、同じビット数を比較し、次いで、辞書式を比較します。
解体側の後に私たちの見解では、経路の距離、このパスの代表者数の中央値は述べています。
私たちは、ビットの最適な数を保証することができます最短経路マップ、最短散歩に沿ってマップを構築するために、(実際のようなBFSを実行した)最短パスを実行するために、ポイント1から始めることができます。

最短経路マップ上の次は、最小の辞書のパスを取る方法を検討します。
辞書順は前よりも後方にあるので、我々は間違いなく最低重量のエッジを確保しようとして行きます。

しかし、問題があります:最小重量よりあるものの場合、あなたは選ぶべきなのでしょうか?
正しい方法は、同時にエッジを拡大することです。接続一緒にリンクされたリストへのこれらの縁の点、及び場合DFSヘッダが通過することができます。

@acceptedコード@

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 2000000;
const int MOD = int(1E9) + 7;
struct edge{
    int to, key;
    edge(int _t=0, int _k=0):to(_t), key(_k) {}
};
vector<edge>G[MAXN + 5];
void addedge(int u, int v, int w) {
    G[u].push_back(edge(v, w));
//  printf("! %d %d %d\n", u, v, w);
}
int cnt;
void func(int u, int v, int id) {
    int p = id;
    while( p ) {
        if( p >= 10 )
            addedge(++cnt, u, p % 10), u = cnt;
        else addedge(v, u, p % 10);
        p /= 10;
    }
}
int d[MAXN + 5], n, m;
void bfs(int x) {
    queue<int>que;
    que.push(x); d[x] = 1;
    while( !que.empty() ) {
        int f = que.front(); que.pop();
        for(int i=0;i<G[f].size();i++) {
            edge p = G[f][i];
            if( !d[p.to] ) {
                d[p.to] = d[f] + 1;
                que.push(p.to);
            }
        }
    }
}
int ans[MAXN + 5], nxt[MAXN + 5];
bool vis[MAXN + 5];
void dfs(int x, int k) {
    int p = x;
    while( p ) ans[p] = k, p = nxt[p];
    for(int i=0;i<10;i++) {
        int q = -1, fir = -1; p = x;
        while( p ) {
            for(int j=0;j<G[p].size();j++) {
                edge &r = G[p][j];
                if( vis[r.to] || d[p] + 1 != d[r.to] )
                    continue;
                if( r.key == i ) {
                    if( q != -1 ) nxt[q] = r.to;
                    else fir = r.to;
                    vis[q = r.to] = true;
                }
            }
            p = nxt[p];
        }
        if( fir != -1 )
            dfs(fir, (10LL*k + i)%MOD);
    }
}
int main() {
    scanf("%d%d", &n, &m), cnt = n;
    for(int i=1;i<=m;i++) {
        int x, y; scanf("%d%d", &x, &y);
        func(x, y, i), func(y, x, i);
    }
    bfs(1), vis[1] = true, dfs(1, 0);
    for(int i=2;i<=n;i++)
        printf("%d\n", ans[i]);
}

@詳細@

元の無向エッジは、私たちが出リッピングが側有向エッジとなることに留意されたいです。

列挙最小量側は、対応するエッジ重みを見つけるために、(すなわち、右側列挙)0~9によって列挙されてもよいです。

おすすめ

転載: www.cnblogs.com/Tiw-Air-OAO/p/11521294.html