2016 四川省赛F. Floyd-Warshall(LCA + brute force)

来源:互联网 发布:算法导论 附加部分答案 编辑:程序博客网 时间:2024/06/04 17:51

这是我第一次使用输入输出外挂,没错,第一次…….. 被卡成傻逼了.

题目链接

Floyd-Warshall

分析

题解icpc_camp 上面已经写的很清楚了.
https://post.icpc-camp.org/d/576-2016-hints
 只需要将至多200个链接非树边的点离散出来,然后在对这两百个点做bfs找出以他们为起点的单元最短路就好了. 不过用并查集来找非树边会T成撒比,找了几份网上的代码,发现几乎都gg了
 这里给一种不用并查集的做法,还记得双连通分量吗?用一个dfn 记录一下dfs序就好了,将环边拿出来.
不过我的码力太差了…..用了FAST IO 才过了

AC code

#include<bits/stdc++.h>#define pb push_back#define mp make_pair#define PI acos(-1)#define fi first#define se second#define INF 0x3f3f3f3f#define INF64 0x3f3f3f3f3f3f3f3f#define random(a,b) ((a)+rand()%((b)-(a)+1))#define ms(x,v) memset((x),(v),sizeof(x))#define eps 1e-8using namespace std;typedef unsigned long long ULL;typedef long long LL;typedef unsigned long long uLL;typedef long double DB;typedef pair<int,int> Pair;const int maxn = 1e5+10;const int  MOD = 1e9+7;int num = 0;int dfs_clock = 0;Pair non_tree[300];std::vector<int> G[maxn];std::map<int, int> id;int tot =0;int idx[300];int dist[200+10][maxn];/*lca*/const int MAX_LOG = 18;int par[maxn][MAX_LOG];int dep[maxn];int dfn[maxn];void dfs(int u,int fa) {    dep[u] =dep[fa]+1;    dfn[u] = ++dfs_clock;    par[u][0] = fa;    for(auto v : G[u]){        if(!dfn[v])dfs(v,u);        else if(v!=fa && dfn[v] < dfn[u])non_tree[num++] = mp(u,v);    }}int lca(int u,int v){    if(dep[u]>dep[v])swap(u,v);    for(int k = 0 ; k<MAX_LOG ; ++k){        if((dep[v] - dep[u]) & 1<<k)            v = par[v][k];    }    if(u==v)return v;    for(int k = MAX_LOG -1; k>=0 ; --k){        if(par[u][k] != par[v][k]){            u = par[u][k];            v = par[v][k];        }    }    return par[u][0];}int vis[maxn];void bfs(int x) {    int u = idx[x];    queue<int> Q;    ms(vis,0);    Q.push(u);    dist[x][u] = 0;    vis[u]=1;    while (!Q.empty()) {        u = Q.front();Q.pop();        for(auto v : G[u]){            if(!vis[v]){                vis[v] =1;                dist[x][v] = dist[x][u]+1;                Q.push(v);            }        }    }}int Scan() {    //输入外挂    int res = 0, flag = 0;    char ch;    if((ch = getchar()) == '-') flag = 1;    else if(ch >= '0' && ch <= '9') res = ch - '0';    while((ch = getchar()) >= '0' && ch <= '9')        res = res * 10 + (ch - '0');    return flag ? -res : res;}void Out(int a) {    //输出外挂    if(a < 0) { putchar('-'); a = -a; }    if(a >= 10) Out(a / 10);    putchar(a % 10 + '0');}int main(){    // ios_base::sync_with_stdio(0);    // cin.tie(0);    // cout.tie(0);    int n,m,q;    n = Scan();    m = Scan();    q = Scan();    tot =0;    num =0;    dfs_clock = 0;    while (m--) {        int u,v;        u = Scan();v = Scan();        G[u].pb(v);        G[v].pb(u);    }    dfs(1,0);    for(int k=1; k<MAX_LOG ; ++k){        for(int i=1 ; i<=n ; ++i)par[i][k] = par[par[i][k-1]][k-1];    }    for(int i =0 ; i<num ; ++i){        int u = non_tree[i].fi,v = non_tree[i].se;        // std::cout << u <<" non tree " << v << '\n';        if(!id.count(u)){            id[u] = tot++;            idx[tot-1] = u;            bfs(tot-1);        }        if(!id.count(v)){            id[v] = tot++;            idx[tot-1] = v;            bfs(tot-1);        }    }    // std::cout << tot << '\n';    // for(auto e : id){    //     std::cout << e.fi <<" " << e.se << '\n';    // }    //for(int i=1 ; i<=n ; ++i)std::cout << dep[i] << '\n';    while (q--) {        int u,v;        u = Scan();        v = Scan();        int ans = dep[u]+dep[v] - 2*dep[lca(u,v)];        for(int i=0 ; i<tot ; ++i){            ans = min(ans, dist[i][u] + dist[i][v]);        }        Out(ans);        putchar('\n');    }    return 0;}
原创粉丝点击